🐻

ZustandのSelector書くのメンドくさい問題にさようなら:Selectorの自動生成で快適Global state管理

2025/03/25に公開

ご注意!

この記事は私が知りたい内容を AI にまとめさせたものです。あしからず🙇‍♂️

TL;DR

  • Zustandにおいて、Selectorを自動生成することで、コードの簡素化とパフォーマンスの向上が可能である。
  • これにより、手動でのSelector記述の手間を省き、パフォーマンスの低下を防ぐことができる。

はじめに

  • Zustandは、Reactのための軽量な状態管理ライブラリであり、シンプルなAPIと高い柔軟性を持つ。
  • 状態管理において、必要な状態のみを購読するSelectorの使用は、不要な再レンダリングを防ぎ、パフォーマンス向上に寄与する。
  • しかし、各状態に対して手動でSelectorを記述することは煩雑であり、コードの冗長化を招く可能性がある。
  • そこで、Selectorを自動生成する方法を導入することで、これらの課題を解決する。

Selectorの自動生成

  • 手動でのSelector記述を省略するために、createSelectors関数を作成する。
  • この関数は、ストア内の各状態に対応するSelectorを自動的に生成する。
import { StoreApi, UseBoundStore } from 'zustand';

type WithSelectors<S> = S extends { getState: () => infer T }
  ? S & { use: { [K in keyof T]: () => T[K] } }
  : never;

const createSelectors = <S extends UseBoundStore<StoreApi<object>>>(
  _store: S,
) => {
  let store = _store as WithSelectors<typeof _store>;
  store.use = {};
  for (let k of Object.keys(store.getState())) {
    (store.use as any)[k] = () => store((s) => s[k as keyof typeof s]);
  }

  return store;
};

このcreateSelectors関数を使用することで、各状態に対するSelectorを自動的に生成し、コードの簡素化が可能となる。

使用例

以下に、createSelectors関数を用いた具体的な使用例を示す。

  1. ストアの定義

    まず、Zustandのcreate関数を用いてストアを定義する。

    import create from 'zustand';
    
    interface BearState {
      bears: number;
      increase: (by: number) => void;
      increment: () => void;
    }
    
    const useBearStoreBase = create<BearState>((set) => ({
      bears: 0,
      increase: (by) => set((state) => ({ bears: state.bears + by })),
      increment: () => set((state) => ({ bears: state.bears + 1 })),
    }));
    
  2. Selectorの自動生成

    定義したストアに対して、createSelectors関数を適用し、Selectorを自動生成する。

    const useBearStore = createSelectors(useBearStoreBase);
    
  3. コンポーネントでの使用

    自動生成されたSelectorを用いて、コンポーネント内で状態やアクションにアクセスする。

    function BearCounter() {
      const bears = useBearStore.use.bears();
      const increment = useBearStore.use.increment();
    
      return (
        <div>
          <h1>{bears} bears around here ...</h1>
          <button onClick={increment}>Add a bear</button>
        </div>
      );
    }
    

このように、createSelectors関数を利用することで、各状態に対するSelectorを自動生成し、コードの簡素化とメンテナンス性の向上を図ることができる。

まとめ

  • ZustandにおけるSelectorの使用は、不要な再レンダリングを防ぎ、パフォーマンス向上に寄与する。
  • createSelectors関数を用いることで、各状態に対するSelectorを自動生成し、手動での記述を省略できる。
  • これにより、コードの簡素化とメンテナンス性の向上が期待できる。

出典・参考

Discussion