Remix v2およびReact Router v7で開発する際に気をつけておきたい点
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZkrvEGAvkHJtABa9UU_D0kag95bnGy3tI6sqhwyrMBNxX-f6IPXdL1rzm5t5YVmKeZFThhUOPA2XvTstL3khytWtb4cDJ861Mj-7bSxkU46yRQe-Ea6aY1D1HN8DDBuUCeh5zW08gfrpP/s800/music_dj_woman.png
【前提】
そこで今回は、Remix v2およびReact v7で開発する際に注意したい点について記載しました。
【Fullstack Data Flowに則って開発する】
Remix 時代からFullstack Data Flowを用意しています。このデータフローに則ることで、外部データの変更およびコンポーネントへの反映を担保してくれます。Next.jsや素のReactで開発する場合はuseStateフックを利用したステート管理を使用しますが、Remix v2およびReact Router v7ではフックの使用をデータフローで暗黙的に制御してくれるので、外部データの変更及び参照のハンドラー内でステートの更新を忘れる可能性が低くなります。データフローの基本的なパターンは以下のとおりです。 code:user.tsx
export async function loader({ request }: LoaderFunctionArgs) {
const res = await getUserData(request) // { name: 'たすくん', message: 'こんにちは' }
return res
}
export default function User {
const data = useLoaderData<typeof Loader>()
return (
<div>
<p>名前: {data.name}</p>
<p>メッセージ: {data.message}</p>
<Form method='post'>
<input type='text' name='name' />
<input type='text' name='message' />
<button type='submit'>更新</button>
</Form>
</div>
)
}
export async function action({ request }: ActionFunctionArgs) {
const data = Object.fromEntries(await request.formData())
await updateUser(data)
}
このように、React Routerのフックを利用することを前提としているため、Reactのフックは必要に応じて利用することになります。例えば、ユーザーの入力に対してインタラクティブにステートの更新をしたい場合は、useStateフックを使うことになります。ステート管理については「State Management」にて言及されています。 データフローに則ることなく、Reactフックを優先して開発することもできますが、Remix v2およびReact Router v7ではCo-locationに則ったConventional Route Foldersによるルート管理ができます。つまり、類似性や関係性の違いを意識したディレクトリ構成になるので、親コンポーネントと子コンポーネントの分離は可能な限り小さくしておいたほうがベターです。このディレクトリ構成はFullstack Data Flowと相性が良く、ステート管理やロジックが必要以上に拡散してしまう事象を防ぐことができるので、開発は可能な限りデータフローに則るほうがよいでしょう。 【フォームデータのバリデーション】
【環境変数をクライアントに渡す】
(公開しても良い環境変数に限りますので注意してください)
環境変数を拾う場合、loaderを利用してサーバーサイドからデータを取得する必要性があります(Node.jsのランタイムを利用する必要があるから)。こちらをコンポーネントやクライアントサイドのフックに渡すことも必要になるでしょう。ユースケースとしては、SSRモードでBFFを用意しない場合などはAPIのドメインが環境によって異なる場合などが挙げられます。詳細は【Remix】loaderで取得した環境変数をclientLoaderおよびclientActionに渡したいを参考にしていただける幸いです。また、RemixのFAQに記載されていますが、対象ルートにおいて記載したloaderはすべて並行実行されます。つまり、rootLoaderで返すデータを他のloaderから取得するといったことはできないので、特にloaderからclientLoaderに環境変数を渡したいときなどは各loaderで環境変数の取得をする必要性があるのでここも注意が必要です。 【loaderやactionを持つコンポーネントを再利用しない】
loaderやactionはその特性上、どのルートに配置するかで挙動が変化します。例えば、users/:user_idにて利用する場合とusers/:user_id/items/:item_idで利用する場合で取得できるパラメータが変化します。よってRemix v2およびReact Router v7ではコンポーネントの再利用性を意識する際にはloaderやactionといったロジックを取り込まないことが重要です。また、副次的にコンポーネントの分離および親子関係はルートのネストに依存することになるので、それ以外の不要なコンポーネントの分離は極力避けておきたいです。
【Loaderから取得したデータの型情報を指定する】
【余談】
今年1年でRemixを使い始め、React Router v7へのマイグレーションを経験しました。シンタックスはReactのフック直接書く機会が少なく、MVCのフレームワークに近い開発体験が得られるので、バックエンドとフロントエンドのエンジニアがシームレスに開発できるフレームワークとしての利便性を享受しています。フレームワークとしてだけではなく、ライブラリとしてのReact Routerのフックを多用するので、そこの学習コストとフレームワーク導入の効果が見合うかどうかは議論が必要でしょう。Remixのメリットについては、もう少しまとめてからこちらのブログで公開しようと考えています。
ここまでご覧いただきありがとうございました。
引き続き、さくらインターネット Advent Calendar 2024 をお楽しみください。