Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】🏃‍♂️State management with Zustand!

2025年09月22日に「Dev.to」が公開したITニュース「🏃‍♂️State management with Zustand!」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

Reactの複雑な状態管理をZustandが解決する。Zustandは小さく高速なライブラリで、Reduxのような定型コードなしに状態を一元管理できる。propsのバケツリレーが不要となり、シンプルな関数で状態を更新できるため、初心者でもコードが読みやすく管理しやすい。

出典: 🏃‍♂️State management with Zustand! | Dev.to公開日:

ITニュース解説

Reactアプリケーションを開発する上で、「状態管理」は避けて通れない重要なテーマである。アプリケーションの「状態」とは、例えばユーザーが入力したデータや、画面に表示するリストの内容、あるいは現在ログインしているユーザーの情報など、時間の経過と共に変化するあらゆるデータを指す。これらの状態を適切に管理しないと、アプリケーションはすぐに複雑化し、開発やメンテナンスが困難になってしまう。

Reactには、コンポーネントごとに状態を管理するためのuseStateというフックがある。しかし、アプリケーションが大きくなり、多くのコンポーネントで同じ状態を共有する必要が出てくると、このuseStateだけでは限界が見えてくる。例えば、ある状態を複数のコンポーネントで共有したい場合、その状態を親コンポーネントに持ち上げ(これを「ステートの引き上げ」と呼ぶ)、子コンポーネントへは「プロップス」として渡す必要が生じる。さらに深い階層にある子コンポーネントへ状態を渡すには、間に存在する関係ない親コンポーネント群にもプロップスとして状態を渡し続ける必要があり、これは「プロップスドリリング」と呼ばれ、コードの可読性や保守性を著しく低下させる要因となる。useContextフックを使うことで、ある程度プロップスドリリングを回避できるものの、それでもまだ管理が複雑になる場合がある。

このようなReactの状態管理の課題を解決するために登場するのが、Zustandのような状態管理ライブラリである。Zustandは、非常にシンプルで軽量なライブラリでありながら、強力な状態管理機能を提供する。Reduxのような他のライブラリと比較して、Zustandは「ボイラープレート」と呼ばれる定型的な記述がほとんど不要である点が大きな特徴である。ボイラープレートとは、特定のフレームワークやライブラリを使う上で必要となる、毎回書かなければならない決まりきったコードのことであり、これが少ないことは開発の効率化とコードの簡潔さに直結する。

Zustandの主なメリットは、その小ささと高速性、そしてReduxにおける「リデューサー」や「アクション」といった複雑な概念が不要であることである。これにより、コードは非常に簡潔になり、開発者は状態管理そのものよりもアプリケーションのロジックに集中できるようになる。また、Reactのフックとの相性も良く、直感的に利用できる。

このシンプルさを体験するために、具体的なアプリケーションでZustandの使い方を見ていく。ここでは、ユーザーリストの表示、追加、削除を行う簡単なアプリケーションを想定する。このアプリケーションを実行するには、Reactのバージョン18以降、Node.jsとnpmがインストールされていることが前提となる。まず、Zustandを利用するためにnpm install zustandコマンドでライブラリをインストールする。

Zustandの中心的な概念は「ストア」である。ストアとは、アプリケーション全体で共有される状態とその状態を変更するための関数(アクション)を一元的に管理する場所である。Zustandでストアを作成するには、create関数を使用する。

例えば、ユーザー情報を管理するストアは以下のように定義できる。create関数に渡された関数内で、ストアが持つ状態とアクションを定義している。usersは、初期値が空の配列として定義された状態であり、これがアプリケーション全体で共有されるユーザーのリストとなる。addUserremoveUserは、このusersの状態を更新するための「アクション」である。

set関数はZustandが提供するもので、これを使うことでストアの状態を更新できる。set((state) => ({ ... }))の形式で使うことで、現在の状態(state)に基づいて新しい状態を安全に計算し、更新することが可能になる。addUserでは、既存のusers配列にnewUserを追加した新しい配列を作成して状態を更新している。removeUserでは、指定されたidと一致しないユーザーだけをフィルタリングして新しい配列を作成し、状態を更新している。このように、Zustandでは直接状態を変更するのではなく、新しい状態オブジェクトを作成してset関数に渡すことで状態を更新する。

ストアを定義したら、次にReactコンポーネントからこのストアの状態やアクションを利用する。Zustandは、定義したストアから自動的にカスタムフック(この例ではuseUserStore)を生成するため、これをReactの標準フックと同じように利用できる。

ユーザーリストを表示するUserListコンポーネントでは、useUserStoreフックを使って、必要な状態(state.users)やアクション(state.removeUser)だけを直接コンポーネント内で選択的に取得する。これにより、関連しない他の状態が更新されても、このコンポーネントが不要に再レンダリングされることを防ぎ、パフォーマンスを向上させる効果がある。また、この方法により、親コンポーネントから子コンポーネントへプロップスをバケツリレーする必要がなくなり、コードがずっと分かりやすくなる。

同様に、新しいユーザーを追加するためのAddUserコンポーネントでは、ストアからaddUserアクションを取得し、フォームの送信時にこれを呼び出す。このAddUserコンポーネントでは、入力フォームのテキスト自体はuseStateでローカルに管理しているが、フォームが送信されたときに実行されるユーザーの追加処理は、ZustandストアのaddUserアクションを呼び出すことで行っている。Date.now()は一時的なIDを生成するために使用している。

最後に、これらのコンポーネントをApp.jsなどの親コンポーネントに配置することで、アプリケーション全体が機能する。App.jsではAddUserUserListを並べて配置するだけで、両方のコンポーネントが同じZustandストアを介してユーザーリストの状態を共有し、操作できるようになる。AddUserでユーザーを追加すれば、すぐにUserListにそのユーザーが表示され、UserListでユーザーを削除すれば、即座にリストから消える。

Zustandを利用することで、Reactアプリケーションの状態管理は非常に楽になる。Reduxで必要とされるリデューサーやディスパッチャーといった追加の概念を学ぶ必要がなく、シンプルな関数呼び出しだけで状態を操作できる。これにより、コードは簡潔で読みやすく保たれ、アプリケーション全体の状態が一箇所に集約されるため、開発者はより効率的に機能を追加し、問題をデバッグできるようになるだろう。Zustandは、Reactの状態管理をより直感的で、開発者にとって負担の少ないものに変える強力なツールである。

関連コンテンツ

関連IT用語