React Context vs Zustand: 使い分けの基準
開発者はReactのステート管理において、よく一つの間違いを犯します。Contextを誤った方法で使用し、その結果生じるパフォーマンスの問題をContextのせいにすることです。
問題の多くは、一つの巨大なコンテキストオブジェクトにあります。そのオブジェクト内の値が変更されると、そのコンテキストを使用しているすべてのコンポーネントが再レンダリングされます。たとえコンポーネントがデータのごく一部しか必要としていなくても、オブジェクト内のあらゆる変更に反応してしまいます。
例えば、通知が30秒ごとに更新される場合、Navbarがユーザー名しか必要としていなくても、Navbarは再レンダリングされます。これがパフォーマンスを低下させる原因となります。
ライブラリを使わなくても、この問題は解決できます。コンテキストを「変更頻度」に基づいて分割しましょう。
一つの大きなコンテキストではなく、以下のように複数に分けます:
• ユーザーデータ用:UserContext
• サイドバーの状態用:UIContext
• アラート用:NotificationContext
これにより、Navbarはユーザーデータが変更されたときのみ再レンダリングされるようになります。この単純な分割だけで、パフォーマンスに関する問題のほとんどは解決します。
以下のような、値が安定しているものにはReact Contextを使用してください: • テーマ • 認証ステータス • 言語設定
また、ContextはServer Componentsとも相性が良いです。一方、Zustandはクライアントサイドでのみ動作します。
特定のステートのみを購読(subscribe)する必要がある場合は、Zustandを使用してください。Zustandを使えば、コンポーネントはステートの特定の「スライス」のみを購読できます。ストアの一部が変更された場合、その特定の部分を監視しているコンポーネントだけが再レンダリングされます。
新しいステートを導入する際は、以下のロジックに従ってください:
React Contextを使用する場合: • データが安定している(テーマ、認証、ロケールなど)。 • SSRやServer Componentsで動作させる必要がある。 • コンテキストを分割することで、Prop Drilling(バケツリレー)を回避したい。
Zustandを使用する場合: • データが頻繁に変更される。 • コンポーネントがステートの特定のスライスを監視する必要がある。 • ロジックが複雑である。
待ってください。APIデータの管理には、どちらも使用しないでください。サーバーからデータを取得する場合は、TanStack Queryを使用しましょう。ContextやZustandには、キャッシュ管理やバックグラウンドでの再取得(refetching)の機能はありません。
まとめ: • 一つの巨大なコンテキストオブジェクトは再レンダリングを引き起こす。分割すること。 • 安定した値に対してZustandを使うのは過剰(overkill)である。 • 頻繁に変わる値にContextを使うと、ラグが発生する。 • サーバーの状態(server state)の管理にZustandを使うのは、適切なツール選びではない。
