Remix 的主要功能之一是它自動使您的 UI 與持久性伺服器狀態保持同步的方式。它分為三個步驟
讓我們考慮一個使用者帳戶編輯路由。該路由模組有三個匯出,我們將填寫並討論它們
export async function loader() {
// provides data to the component
}
export default function Component() {
// renders the UI
}
export async function action() {
// updates persistent data
}
路由檔案可以匯出一個 loader
函數,該函數向路由組件提供資料。當使用者導航到匹配的路由時,資料會先載入,然後才渲染頁面。
import type { LoaderFunctionArgs } from "@remix-run/node"; // or cloudflare/deno
import { json } from "@remix-run/node"; // or cloudflare/deno
export async function loader({
request,
}: LoaderFunctionArgs) {
const user = await getUser(request);
return json({
displayName: user.displayName,
email: user.email,
});
}
export default function Component() {
// ...
}
export async function action() {
// ...
}
路由檔案的預設匯出是渲染的組件。它使用 useLoaderData
讀取載入器資料
import type { LoaderFunctionArgs } from "@remix-run/node"; // or cloudflare/deno
import { json } from "@remix-run/node"; // or cloudflare/deno
import { useLoaderData, Form } from "@remix-run/react";
export async function loader({
request,
}: LoaderFunctionArgs) {
const user = await getUser(request);
return json({
displayName: user.displayName,
email: user.email,
});
}
export default function Component() {
const user = useLoaderData<typeof loader>();
return (
<Form method="post" action="/account">
<h1>Settings for {user.displayName}</h1>
<input
name="displayName"
defaultValue={user.displayName}
/>
<input name="email" defaultValue={user.email} />
<button type="submit">Save</button>
</Form>
);
}
export async function action() {
// ...
}
最後,當提交表單時,會呼叫與表單的 action 屬性匹配的路由上的動作。在本例中,它是相同的路由。表單欄位中的值將在標準的 request.formData()
API 上可用。請注意,輸入上的 name
屬性與 formData.get(fieldName)
getter 相關聯。
import type {
ActionFunctionArgs,
LoaderFunctionArgs,
} from "@remix-run/node"; // or cloudflare/deno
import { json } from "@remix-run/node"; // or cloudflare/deno
import { useLoaderData, Form } from "@remix-run/react";
export async function loader({
request,
}: LoaderFunctionArgs) {
const user = await getUser(request);
return json({
displayName: user.displayName,
email: user.email,
});
}
export default function Component() {
const user = useLoaderData<typeof loader>();
return (
<Form method="post" action="/account">
<h1>Settings for {user.displayName}</h1>
<input
name="displayName"
defaultValue={user.displayName}
/>
<input name="email" defaultValue={user.email} />
<button type="submit">Save</button>
</Form>
);
}
export async function action({
request,
}: ActionFunctionArgs) {
const formData = await request.formData();
const user = await getUser(request);
await updateUser(user.id, {
email: formData.get("email"),
displayName: formData.get("displayName"),
});
return json({ ok: true });
}
當使用者提交表單時
fetch
將表單資料傳送到路由動作,並且可以通過諸如 useNavigation
和 useFetcher
之類的 hook 獲得待處理的狀態。useLoaderData
從伺服器返回更新的值,並且待處理的狀態會返回到閒置狀態。通過這種方式,UI 會與伺服器狀態保持同步,而無需編寫任何用於同步的程式碼。
除了 HTML 表單元素之外(例如,響應拖放或 onChange 事件),還有多種提交表單的方式。此外,還有很多關於表單驗證、錯誤處理、待處理狀態等內容需要討論。我們稍後將討論所有這些內容,但這就是 Remix 中資料流程的要點。
當您從伺服器傳送 HTML 時,最好在 JavaScript 載入之前就使其正常工作。Remix 中典型的資料流程會自動執行此操作。流程是相同的,但瀏覽器會執行一些工作。
當使用者在 JavaScript 載入之前提交表單時
fetch
),並且瀏覽器的待處理狀態會啟動(旋轉的圖示)