【入門編】 Zustandによるストアの作成とフックの利用 – React実践ガイド

こんにちは!Reactの学習、毎日お疲れ様です。

画面上のボタンを押したときに数字が変わったり、お買い物かごの中身が増えたりする「状態(ステート)」の管理、最初は`useState`で楽しく作れていたはずなのに、アプリが大きくなるにつれて「あれ?このデータ、あっちのコンポーネントでも使いたいのに、どうやって渡せばいいんだっけ…?」と、いわゆる「プロパティのバケツリレー(プロップドリル)」地獄にハマって頭を抱えていませんか?

大丈夫ですよ。その悩み、世界中のすべてのReact開発者が一度は通る道です。

今回は、そんな複雑なデータの受け渡しを驚くほどシンプルにしてくれる、いま大人気の軽量状態管理ライブラリ「Zustand(ツースタンド)」について、一緒に優しく紐解いていきましょう!

—

そもそもZustandってなに?お買い物かごで例えてみよう

Reactには標準で`useState`や、少し本格的な`useContext`という仕組みが用意されています。これらも素晴らしい機能なのですが、アプリが少し複雑になってくると、お作法が面倒だったり、コードがごちゃごちゃしがちです。

そこで登場するのがZustandです。ドイツ語で「状態」を意味するこのライブラリは、とにかくシンプルで、おまじないが少ないのが最大の魅力です。

身近な例えで考えてみましょう。
あなたは今、オンラインショップを作っています。画面のあちこちに「お買い物かごに入っている商品の数」を表示したいとします。

  • 今までの方法(useStateなど):

親から子へ、子から孫へと、使わないコンポーネントにも「はい、これ持ってて!」とバケツリレー形式でデータを渡し続ける必要があります。途中で「やっぱりこのデータ要る!」となったら大改造です。

  • Zustandを使った場合:

お店の隅っこに、誰でも自由にアクセスできる「みんなのお買い物かご(ストア)」を一つポツンと置きます。
欲しい人はそこから勝手にかごの中身を覗き、レジ係の人はそこへ商品を追加する。バケツリレーなんて必要ありません。どの階層のコンポーネントからでも、その「お買い物かご」にダイレクトにアクセスできるのです。

すごくすっきりしませんか?それでは実際に、その「お買い物かご」をコードで作ってみましょう!

—

ステップ1:Zustandでストア(お買い物かご)を作ってみよう

まずは、Zustandをインストールしている前提で話を進めますね(もしまだなら `npm install zustand` でインストールしておいてください!)。

ここでは、ボタンを押すと数字が増減する「カウンター」を例に、ストアを作ってみます。プロジェクトの中に `useCounterStore.js` というファイルを作ってみてください。

import { create } from ‘zustand’;

// create関数を使って、みんなで共有する「ストア」を作ります
// ここが、いわゆる「お店のお買い物かご」を置く場所です!
export const useCounterStore = create((set) => ({
// 1. 管理したいデータ(状態)の初期値
count: 0,

// 2. データを変更するための関数(アクション)
// カウントを増やす処理
increase: () => set((state) => ({ count: state.count + 1 })),

// カウントを減らす処理
decrease: () => set((state) => ({ count: state.count – 1 })),

// カウントをゼロにリセットする処理
reset: () => set({ count: 0 }),
}));

たったこれだけです!
`set` という見慣れない言葉が出てきましたが、これは「今ある状態をこう書き換えるよ」とZustandにお願いするための魔法の杖だと思ってください。難しいことは考えず、`set((state) => ({ … }))` というお決まりの形として覚えてしまって大丈夫です。

—

ステップ2:コンポーネントで「お買い物かご」を使ってみよう

さて、先ほど作ったストア(みんなのお買い物かご)を、実際のReactコンポーネントで使ってみましょう。驚くほど簡単に取り出せます。

import React from ‘react’;
// さっき作ったストアをインポートします
import { useCounterStore } from ‘./useCounterStore’;

export function CounterComponent() {
// ストアから、使いたいデータと関数だけを「つまみ食い」して取り出します!
// 必要なものだけを指定できるので、無駄な再レンダリングが起きません。
const count = useCounterStore((state) => state.count);
const increase = useCounterStore((state) => state.increase);
const decrease = useCounterStore((state) => state.decrease);
const reset = useCounterStore((state) => state.reset);

return (

);
}

どうでしょう?コンポーネントの中にごちゃごちゃした状態管理のコードを書かなくてよくなったので、見た目がとてもスッキリしていませんか?

さらに感動的なのは、この `CounterComponent` がアプリのどこにあろうとも、兄弟コンポーネントであろうとも、まったく同じ書き方で同じ `count` を共有できるという点です。もうプロパティのバケツリレーに悩む夜とはお別れです!

—

初学者がつまずきやすいポイントと、優しく温かいアドバイス

Zustandは非常にシンプルですが、使い始めの頃に「あれ?」となりがちなポイントがいくつかあります。ここでこっそり共有しておきますね。

1. 「どれを取り出せばいいの?」迷ったら個別に取り出そう

Zustandのストアからは、オブジェクト全体を丸ごと取り出すこともできます。

// こう書きたくなっちゃうけれど…
const { count, increase } = useCounterStore();

これでも動くことは動くのですが、ストア内の「関係ないデータ」が更新されたときにもこのコンポーネントが再レンダリングされてしまい、パフォーマンスの低下につながることがあります。
ですので、基本的には先ほどのコードのように、使うデータや関数を1つずつ指定して取り出すのが、パフォーマンス面でも安全でおすすめです!

// こっちの方が安全でスマート!
const count = useCounterStore((state) => state.count);
const increase = useCounterStore((state) => state.increase);

2. 非同期処理(API通信など)もそのまま書けちゃう

「お買い物かごのデータをサーバーから取ってくる」といった非同期処理も、Zustandのストア内なら特別なミドルウェアなしでスッキリ書けます。

export const useUserStore = create((set) => ({
user: null,
loading: false,

// 非同期の関数も、ストアの中にそのまま定義できちゃいます
fetchUser: async (userId) => {
set({ loading: true });
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
const data = await response.json();
set({ user: data, loading: false });
} catch (error) {
console.error(“データの取得に失敗しました”, error);
set({ loading: false });
}
},
}));

コンポーネント側からは、この `fetchUser` を呼び出すだけ。裏側の複雑な通信処理をコンポーネントから隠蔽できるので、コードがぐっと美しくなります。

—

まとめ

今回は、Zustandの基本的な概念から、実際のストアの作り方、コンポーネントでの利用方法までを優しく解説しました。

  • Zustandとは?:どこからでもアクセスできる、シンプルで軽量なお買い物かご(ストア)のような状態管理ライブラリ。
  • `create` 関数:データと、それを変更する関数をひとまとめにする魔法の関数。
  • フックの利用:必要なデータだけをつまみ食いして、コンポーネントをスッキリ保つ。

Reactの複雑な状態管理に心が折れそうになっていた方こそ、Zustandのこの「肩の力の抜けた使いやすさ」に触れると、きっと開発が何倍も楽しくなるはずです。

最初は完璧に使いこなせなくても大丈夫。まずは小さなカウンターや、お気に入りボタンの切り替えなどから、気軽にあなたのアプリに取り入れてみてくださいね。
あなたのReactの旅が、もっとワクワクする快適なものになりますように!

コメント

タイトルとURLをコピーしました