Open6
Remix学習
はじめに
Reactのフレームワークとして、Remixがシンプルでわかりやすいと聞いたので公式ドキュメントを中心に気になったことをまとめていこうと思う。
チュートリアル
とりあえずこれやれば、なんとなくのイメージはつかめるだろう
Form vs. fetcher
下記のAPIを対象にいつ、なぜ使うのかを明確にすることが目標。
- <Form>
- useActionData
- useFetcher
- useNavigation
URLに
- URL変更が必要である
- ページ間の移動や遷移、またはレコード作成や削除などの特定アクション実行後。
- URLの変更が必要でない
- 現在のビューのコンテキストや主なコンテンツを大幅に変更しないアクションの場合。
- 個々のフィールド更新や、新しい URL やページのリロードが不要なデータ操作が含まれる場合があり。ポップオーバーやコンボ ボックスなどのフェッチャーを使用したデータのロードにも当てはまる。
Server vs. Client Code Execution
Remixではビルドステップ時に、サーバー用とクライアント用のビルドを作成する。
- サーバービルドの場合、すべてが1つのモジュールとなる
- クライアントビルドの場合、複数のバンドルに分割される(ブラウザ読み込み最適化)
以下のルートモジュールの場合、action
headers
loader
がクライアントから削除。
routes/settings.tsx
import type {
ActionFunctionArgs,
HeadersFunction,
LoaderFunctionArgs,
} from "@remix-run/node";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { getUser, updateUser } from "../user";
// クライアントビルドから削除
export const headers: HeadersFunction = () => ({
"Cache-Control": "max-age=300, s-maxage=3600",
});
// クライアントビルドから削除
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 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 });
}
また、*.client.tsx
および *.server.tsx
のルールに従えば、クライアントまたはサーバーからコードを強制的に取り出すことが可能。これはどういうとき使うんだ?
-
*.client.ts
- ファイルをサーバーバンドルから強制的に除外
- このモジュールからエクスポートされた値は、サーバー上ではすべてundefinedとなる
- useEffectとクリックハンドラのようなユーザーイベントのみで使用可能
-
*.server.ts
- ファイル名に付与すると、クライアントバンドルから強制的に削除
https://remix.run/docs/en/main/file-conventions/-client
https://remix.run/docs/en/main/file-conventions/-server
- ファイル名に付与すると、クライアントバンドルから強制的に削除
状態管理
Reactでの状態管理
通常のReactでは、状態管理 = キャッシュ管理を指す事が多い。これはサーバーが真の情報源であり、クライアントの状態は主にキャッシュとして機能するため。
Remixによる状態の簡素化
- ローダー、アクション、フォーム機能は再検証の自動同期を備えており、BEとFEのギャップをシームレスに橋渡ししている。
- キャッシュ、ネットワーク通信、データ再検証を管理する必要がないためコンポーネント内のサーバーの状態を直接使用可能。
1. ネットワーク関連の状態
Remixがすでに管理しているもの
-
useNavigation
- navigation.state、navigation.formData、navigation.location などにアクセス可能
-
useFetcher
- fetcher.state、fetcher.formData、fetcher.data などとやり取りが簡潔になる
-
useLoaderData
- ルートのデータにアクセス可能
-
useActionData
- 最新のアクションのデータにアクセス可能
2. Remixでのデータ保存
stateとして保存したいデータは、Remixの自然な場所にある
- URL Search Params:URL 内のパラメータ
- Cookies:ユーザーデバイス保存される小さなデータ
- Server Sessions:サーバー管理のユーザーセッション
- Server Caches:サーバー側でのデータキャッシュ
永続的なUIの状態
状態には以下3つの方法が存在し、それぞれトレードオフがある。
- React state: シンプルだが一時的な状態管理を提供
- ローカル ストレージ: 永続性を提供するが、同期要件と UI のちらつきがある。
- Cookie: 追加のコード量を犠牲にして、堅牢で永続的な状態管理を実現。