<Form>
<Form>
组件扩展了 HTML <form>
元素,以提供对 预取 加载 UI 的支持, 提交时进行客户端导航,并实现渐进增强。
对于更新 URL 搜索参数的表单很有用,因为它减少了实现上述目标所需的样板代码。
基本用法
import Form from 'next/form'
export default function Page() {
return (
<Form action="/search">
{/* On submission, the input value will be appended to
the URL, e.g. /search?query=abc */}
<input name="query" />
<button type="submit">Submit</button>
</Form>
)
}
参考
<Form>
组件的行为取决于 action
属性是否传递了 string
或 function
。
- 当
action
是一个字符串时,<Form>
的行为类似于使用GET
方法的原生 HTML 表单。表单数据被编码为 URL 中的搜索参数,当表单提交时,它会导航到指定的 URL。此外,Next.js - 当
action
是一个函数(服务器操作)时,<Form>
的行为类似于 React 表单,在表单提交时执行操作。
action
(字符串) 属性
当 action
是字符串时,<Form>
组件支持以下属性
属性 | 示例 | 类型 | 必填 |
---|---|---|---|
action | action="/search" | string (URL 或相对路径) | 是 |
replace | replace={false} | 布尔值 | - |
scroll | scroll={true} | 布尔值 | - |
prefetch | prefetch={true} | 布尔值 | - |
action
: 表单提交时要导航到的 URL 或路径。- 空字符串
""
将使用更新的搜索参数导航到同一路由。
- 空字符串
replace
: 替换当前历史状态,而不是将其推送到 浏览器历史记录 堆栈。默认为false
。scroll
: 控制导航期间的滚动行为。默认为true
,这意味着它将滚动到新路由的顶部,并为前后导航保持滚动位置。prefetch
: 控制表单在用户视口中可见时是否应预取路径。默认为true
。
action
(函数) 属性
当 action
是函数时,<Form>
组件支持以下属性
属性 | 示例 | 类型 | 必填 |
---|---|---|---|
action | action={myAction} | function (服务器操作) | 是 |
action
:提交表单时要调用的服务器操作。更多信息请参见React 文档。
注意:当
action
为函数时,replace
和scroll
属性会被忽略。
注意事项
formAction
:可在<button>
或<input type="submit">
字段中使用,以覆盖action
属性。Next.js 将执行客户端导航,但是这种方法不支持预取。- 当使用
basePath
时,也必须将其包含在formAction
路径中。例如:formAction="/base-path/search"
。
- 当使用
key
:不支持将key
属性传递给字符串action
。如果要触发重新渲染或执行变异,请考虑使用函数action
。
onSubmit
:可用于处理表单提交逻辑。但是,调用event.preventDefault()
将覆盖<Form>
的行为,例如导航到指定的 URL。method
,encType
,target
:不支持,因为它们会覆盖<Form>
的行为。- 同样,
formMethod
、formEncType
和formTarget
分别可用于覆盖method
、encType
和target
属性,使用它们将回退到原生浏览器行为。 - 如果需要使用这些属性,请改用 HTML
<form>
元素。
- 同样,
<input type="file">
:当action
为字符串时,使用此输入类型将匹配浏览器行为,提交文件名而不是文件对象。
示例
指向搜索结果页面的搜索表单
可以通过将路径作为action
传递来创建一个导航到搜索结果页面的搜索表单。
import Form from 'next/form'
export default function Page() {
return (
<Form action="/search">
<input name="query" />
<button type="submit">Submit</button>
</Form>
)
}
当用户更新查询输入字段并提交表单时,表单数据将被编码为 URL 中的搜索参数,例如:/search?query=abc
。
注意:如果将空字符串
""
传递给action
,表单将导航到具有更新搜索参数的同一路由。
在结果页面上,可以使用searchParams
page.js
属性访问查询,并用它从外部来源获取数据。
import { getSearchResults } from '@/lib/search'
export default async function SearchPage({
searchParams,
}: {
searchParams: { [key: string]: string | string[] | undefined }
}) {
const results = await getSearchResults(searchParams.query)
return <div>...</div>
}
当<Form>
出现在用户的视口中时,/search
页面上的共享 UI(如layout.js
和loading.js
)将被预取。提交后,表单将立即导航到新路由,并在获取结果时显示加载 UI。可以使用loading.js
设计回退 UI。
export default function Loading() {
return <div>Loading...</div>
}
为了应对共享 UI 尚未加载的情况,可以使用useFormStatus
向用户显示即时反馈。
首先,创建一个组件,在表单处于挂起状态时显示加载状态。
'use client'
import { useFormStatus } from 'react-dom'
export default function SearchButton() {
const status = useFormStatus()
return (
<button type="submit">{status.pending ? 'Searching...' : 'Search'}</button>
)
}
然后,更新搜索表单页面以使用SearchButton
组件。
import Form from 'next/form'
import { SearchButton } from '@/ui/search-button'
export default function Page() {
return (
<Form action="/search">
<input name="query" />
<SearchButton />
</Form>
)
}
使用服务器操作进行变异
可以通过将函数传递给action
属性来执行变异。
import Form from 'next/form'
import { createPost } from '@/posts/actions'
export default function Page() {
return (
<Form action={createPost}>
<input name="title" />
{/* ... */}
<button type="submit">Create Post</button>
</Form>
)
}
变异后,通常会重定向到新资源。可以使用next/navigation
中的redirect
函数导航到新的帖子页面。
注意:由于表单提交的“目标”在操作执行之前是未知的,因此
<Form>
无法自动预取共享 UI。
'use server'
import { redirect } from 'next/navigation'
export async function createPost(formData: FormData) {
// Create a new post
// ...
// Redirect to the new post
redirect(`/posts/${data.id}`)
}
然后,在新页面中,可以使用params
属性获取数据。
import { getPost } from '@/posts/data'
export default async function PostPage({ params }: { params: { id: string } }) {
const data = await getPost(params.id)
return (
<div>
<h1>{data.title}</h1>
{/* ... */}
</div>
)
}
更多示例请参见服务器操作文档。
这篇文章对您有帮助吗?