📝

Next.js で React Server Components を試してみた

こんにちは、フォルシアエンジニアの籏野です。

先日Next.js 13.4が発表され、App Router が Stable 版になりました。
App Router では最新の React の機能を利用することが可能になっており、その中でも特に注目したいのが React Server Components です。

これまでの Next.js では SSR 時にフェッチしたデータを利用する場合、getServerSidePropsgetStaticPropsを利用していました。
これらの関数で取得したデータをコンポーネントに props として渡して SSR を行っていましたが、props のバケツリレーが長くなってわかりづらくなったり、非同期の処理に時間がかかって初期の描画が遅くなるといった問題がありました。

React Server Components(以後、RSC)の大きな特徴として、コンポーネントを返す関数自体を非同期関数として扱うことが可能になりました。
これにより、コンポーネント内でデータの取得を行ったり、コンポーネント内の処理が完了する前に描画を行うといったことができるようになりました。

React の新しい機能ははこれまでの React の考え方とは大きく異なる部分も多く、筆者自身ハードルを感じていました。
ですが、今回の記事の執筆を通してそのハードルは幾分か下がったように感じています。
同じように RSC に興味を持っている方の参考になれば幸いです。

準備

create-next-app で簡単に環境を用意します。

$ pnpm create next-app

今回の記事ではJSONPlaceholder を利用して架空のブログサイトをイメージして作成していきます。

今回作成したものは全て以下のリポジトリに置いています。
next devでアプリを起動すれば、 http://localhost:3000/app_sample にアクセスしページを確認できます。

https://github.com/taku-hatano/rsc-exercise

記事一覧コンポーネントの実装

記事一覧を表示するコンポーネントを React Server Components(以後 RSC)で実装すると以下のようになります。
冒頭で説明した通り、非同期関数として実装しており関数内でデータの取得を行っていることがわかります

https://github.com/taku-hatano/rsc-exercise/blob/main/src/components/PostList.tsx#L23-L42

App Router でページを作成する

App Router では app 以下に page.tsx を配置することで、ファイルのパスに対応したページを作成することができます。

https://github.com/taku-hatano/rsc-exercise/blob/main/src/app/list/page.tsx#L4-L18

実際に作成したページにアクセスしてみると、以下のように Loading が表示された後に記事一覧が表示されることが確認できます。

これだけ見ると、クライアントサイドでデータの取得/レンダリングが行われているように見えますが、ブラウザの開発者ツールや next devのログを見てみると、サーバーサイドでデータの取得が行われていることが分かります。

データ取得が完了していないにも関わらず、画面のレンダリングを先行して行えるようにしているのが Suspence というコンポーネントになります。
Suspense で囲われたコンポーネント内の非同期処理が終わっていない場合、fallbackに渡したコンポーネントを先に描画し、非同期処理が完了した時点でコンポーネントを描画してくれるようになります。
これにより、処理に時間がかかるコンポーネントを利用している場合でも、ユーザーのストレスにならずに描画することができます。

Client Components の利用

なんらかユーザーの操作を受け付けたり、ステートを持ったりする場合にはサーバーサイドではなくクライアントでコンポーネントをレンダリングする必要があります。
このような場合には、ファイルの先頭に "use client"と明記する必要があります。

例として各記事の詳細情報を API で取得し、トグルボタンで詳細情報の表示/非表示を切り替えるようなコンポ―ネントを作成してみます。

トグルボタンについてはユーザーの操作を受け付けるため、Client Components として実装します。
https://github.com/taku-hatano/rsc-exercise/blob/main/src/components/ToggleButton.tsx

詳細情報のコンポーネントに関しては、先の記事一覧コンポーネントと同様に RSC で実装しました。
これらを組み合わせ、以下のようなコンポーネントを作成しました。

https://github.com/taku-hatano/rsc-exercise/blob/main/src/components/PostListWithDetail.tsx#L23-L48

ポイントは、RSC で作られた PostDetail コンポーネントを childeren として ToggleButton に渡しているところです。
RSC を利用する際のルールとして、Client Components から Server Components を呼び出すことはできないのです。

実際の画面表示は以下のようになっています。
各詳細情報を Suspense で囲っているので、詳細情報の取得が完了する前に画面がレンダリングされ、ユーザーの操作も開始できていることが見て取れます。

まとめ

Next.js への React Server Components の導入は、これまでのコンポーネント作成とは異なる観点も増えていて、筆者自身も少なからずハードルを感じていました。
ただ今回の記事作成にあたり、React Server Components/Suspense/Client Components との関係性を見ることができたことで、実際にアプリを作成するイメージも湧いてきた気がしています。

Next.js の新しい機能も使いこなして、より良いアプリを作成していきたいですね。

この記事を書いた人

籏野 拓
2018 年新卒入社

FORCIA Tech Blog

Discussion