<Form>
<Form>
元件擴展了 HTML <form>
元素,以提供 預取 載入 UI 的功能, 提交時的客戶端導航和漸進式增強。
它適用於更新網址搜尋參數的表單,因為它減少了實現上述功能所需的樣板程式碼。
基本用法
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} | boolean(布林值) | - |
scroll | scroll={true} | boolean(布林值) | - |
prefetch | prefetch={true} | boolean(布林值) | - |
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 將執行 client-side 導航,但這種方法不支援預取。- 使用
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
屬性,表單將會導向到具有更新後搜尋參數的相同路由。
在結果頁面上,您可以使用 page.js
的 searchParams
屬性存取查詢,並使用它從外部來源擷取資料。
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
設計 fallback 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>
)
}
如需更多範例,請參閱 伺服器動作 文件。
這有幫助嗎?