Form
Form
组件是对 HTML 中form
标签的一个封装,它的功能只是模拟了 HTML 中表单的各种操作,直接使用Form
组件进行表单的提交一样会引起页面的导航。需要注意的是这个Form
组件并不支持表单验证等表单支持库中提供的功能。
如果不想引起页面的导航操作,需要使用useFetcher()
Hook。
跟 HTML 中的form
标签一样,Form
组件中常用的属性也是method
和action
,其中method
依旧是用来定义表单的提交方法,而action
也是用来定义表单的提交路径的。如果Form
组件在使用的时候没有定义action
属性,那么Form
组件将默认提交到当前组件的action
方法或者是在组件树中拥有action
方法的距离当前组件最近的父级组件。
表单在提交并完成action
方法的调用后,会调用loader
方法来刷新页面上的数据。
get
方法
如果将Form
组件的method
属性定义为get
,即采用GET
方法提交表单,那么整个表单将产生一个导航到action
属性的查询,所有的表单内容将形成一套查询串(SearchParams)。例如以下这个搜索表单的例子。
function SearchForm() {
return (
<Form method="get" action="/products">
<input type="text" name="k" placeholder="请输入检索关键字" />
<button type="submit">查询</button>
</Form>
);
}
在这个示例中提交表单将导航到/prodcuts?k=...
的 URL 上。提交method
为get
的表单会调用路由中定义的loader
方法。
replace
replace
属性主要是用来清除和重置浏览历史堆栈的,但是根据Form
组件上其他属性的不同取值,会有不同的默认行为。根据 React Router 文档中的列举,这些默认行为大致有以下这些。
method
取值为get
时,replace
为false
。- 根据
action
属性的不同,replace
存在不同的默认取值。action
方法抛出异常,replace
为false
;action
导航至当前页面,replace
为true
;action
导航到其他位置,replace
为false
;- 其他情况下,
replace
都为false
。
reloadDocument
为Form
组件设置reloadDocument
属性,将会使Form
组件跳过 React Router 的表单提交操作,直接使用浏览器中的原生表单提交操作,并使页面产生刷新。
preventScrollReset
这个属性是需要搭配<ScrollRestoration>
组件使用的,<ScrollRestoration>
组件可以在表单提交并导航到新页面时重置页面的滚动条到之前的位置。但是如果设置Form
组件上的preventScrollReset
属性为true
,将会阻止页面重置滚动条的动作。
useSubmit
useSubmit()
Hook 可以返回一个方法用于提供开发者采用代码方式提交表单。其返回的函数接受两种参数,第一种是任意的表单或者表单控件的ref
,第二种是一个FormData
类型的表单数据以及配置表单提交目标和方法的配置项。
其使用方法十分简单,如以下示例所示。
/* 示例一:用在Form组件上 */
function SearchForm() {
const submit = useSubmit();
return (
<Form onChange={(event) => submit(event.currentTarget)}>
{/* 实际表单内容 */}
</Form>
);
}
/* 示例二:用在提交按钮上 */
function SearchForm() {
const ref = useRef(null);
const submit = useSubmit();
const handleAction = useCallback(() => {
submit(ref.current);
}, [submit, ref]);
return (
<Form>
<button type="submit" ref={ref}>
提交
</button>
{/* 其他代码 */}
</Form>
);
}
/* 示例三:直接提交表单内容 */
const formData = new FormData();
formData.append("field", someVlaue);
submit(formData);