LoginSignup
0
0

【備忘録】zustandを使って最速でグローバルステートを実装する

Last updated at Posted at 2024-04-07

はじめに

この記事は zustand の使い方の 備忘録 です。

zustandとは

かなり シンプル に使える グローバル状態管理ライブラリ です。

インストール

npm install zustand

最速で Global state を定義する

Global statecreate関数第1引数set第2引数get
戻り値オブジェクトcallback関数 を渡すことで作成します。

戻り値のオブジェクトGlobal state記述 していきます。
オブジェクト内に stateプロパティ として 記述
更新関数メソッド として 記述 します。

更新関数 の中では set の引数に state名と更新したい値オブジェクト を渡します。

下記が 簡単な実装例 です。

app/page.js
"use client";
import { create } from "zustand";

const useStore = create((set, get) => ({
  score: 0,
  setScore10: () => set({ score: 10 }),
}));

export default function Home() {
  const { score, setScore10 } = useStore();

  return (
    <>
    <h1>scoreの値:{score}</h1>
    <button onClick={() => setScore10()}>scoreを10に変更するボタン</button>
    </>
  );
}

setの中で現在の state の値を使う

第2引数の get を使うことで現在の state を取得出来ます。

下記に 実装例 を示します。

app/page.js
"use client";
import { create } from "zustand";

const useStore = create((set, get) => ({
  score: 0,
  setScore10: () => set({ score: 10 }),
  scoreIncrement: () => set({ score: get().score + 1 })
}));

export default function Home() {
  const { score, setScore10, scoreIncrement } = useStore();

  return (
    <>
    <h1>scoreの値:{score}</h1>
    <button onClick={() => setScore10()}>scoreを10に変更するボタン</button>
    <button onClick={() => scoreIncrement()}>scoreを1増加するボタン</button>
    </>
  );
}

set の引数に callback関数 を渡すと第1引数が 現在のstate になるので 第1引数
上手く使うことでも 実装 出来ます。

下記に 実装例 を示します。

app/page.js
"use client";
import { create } from "zustand";

const useStore = create((set, get) => ({
  score: 0,
  setScore10: () => set({ score: 10 }),
  scoreIncrement: () => set({ score: get().score + 1 }),
  scoreDecrement: () => set( (state) => ({ score: state.score - 1 }) )
}));

export default function Home() {
  const { score, setScore10, scoreIncrement, scoreDecrement } = useStore();

  return (
    <>
    <h1>scoreの値:{score}</h1>
    <button onClick={() => setScore10()}>scoreを10に変更するボタン</button>
    <button onClick={() => scoreIncrement()}>scoreを1増加するボタン</button>
    <button onClick={() => scoreDecrement()}>scoreを1減少するボタン</button>
    </>
  );
}

Global state から state と 更新関数を取りだす方法

定義されたGlobal state から state と 更新関数 を取り出すには
1.useStore() の戻り値を 分割代入 する。
2.useStore((state) => state.score)) のように useStoreの引数にcallback関数 を渡す。
2種類 の方法があります。

このうち 2 は実行された時にコンポーネントの再描画が 発生しない ので
こちらを使う方がパフォーマンスが良い です。

パフォーマンスが良い方法 の実装例を下記に示します。

app/page.js
"use client";
import { create } from "zustand";

const useStore = create((set, get) => ({
  score: 0,
  setScore10: () => set({ score: 10 }),
  scoreIncrement: () => set({ score: get().score + 1 }),
  scoreDecrement: () => set( (state) => ({ score: state.score - 1 }) )
}));

export default function Home() {
  const score = useStore((state) => state.score);
  const setScore10 = useStore((state) => state.setScore10);
  const scoreIncrement = useStore((state) => state.scoreIncrement);
  const scoreDecrement = useStore((state) => state.scoreDecrement);

  return (
    <>
    <h1>scoreの値:{score}</h1>
    <button onClick={() => setScore10()}>scoreを10に変更するボタン</button>
    <button onClick={() => scoreIncrement()}>scoreを1増加するボタン</button>
    <button onClick={() => scoreDecrement()}>scoreを1減少するボタン</button>
    </>
  );
}

パフォーマンスの良い方法分割代入 する 実装例 を示します。

app/page.js
"use client";
import { create } from "zustand";
import { shallow } from 'zustand/shallow';

const useStore = create((set, get) => ({
  score: 0,
  setScore10: () => set({ score: 10 }),
  scoreIncrement: () => set({ score: get().score + 1 }),
  scoreDecrement: () => set( (state) => ({ score: state.score - 1 }) )
}));

export default function Home() {
  const { score, setScore10, scoreIncrement, scoreDecrement } = useStore((state) => ({
    score: state.score,
    setScore10: state.setScore10,
    scoreIncrement: state.scoreIncrement,
    scoreDecrement: state.scoreDecrement
  }), shallow);

  return (
    <>
    <h1>scoreの値:{score}</h1>
    <button onClick={() => setScore10()}>scoreを10に変更するボタン</button>
    <button onClick={() => scoreIncrement()}>scoreを1増加するボタン</button>
    <button onClick={() => scoreDecrement()}>scoreを1減少するボタン</button>
    </>
  );
}

useStore に渡す callback関数 の戻り値を オブジェクト にして
第2引数shallow を渡します。

追記:更新関数に渡された引数を更新関数の中で使う

入力された値を コンソールに出力 することで 更新関数に渡された引数更新関数の中
使う例を下記に示します。

app.page.js
"use client";
import { create } from "zustand";
import { shallow } from 'zustand/shallow';

const useStore = create((set, get) => ({
  score: 0,
  setScore10: () => set({ score: 10 }),
  scoreIncrement: () => set({ score: get().score + 1 }),
  scoreDecrement: () => set( (state) => ({ score: state.score - 1 }) ),
  getArgs: (args) => {
    console.log(args);
  } 
}));

export default function Home() {
  const { score, setScore10, scoreIncrement, scoreDecrement, getArgs } = useStore((state) => ({
    score: state.score,
    setScore10: state.setScore10,
    scoreIncrement: state.scoreIncrement,
    scoreDecrement: state.scoreDecrement,
    getArgs: state.getArgs
  }), shallow);

  return (
    <>
    <h1>scoreの値:{score}</h1>
    <button onClick={() => setScore10()}>scoreを10に変更するボタン</button>
    <button onClick={() => scoreIncrement()}>scoreを1増加するボタン</button>
    <button onClick={() => scoreDecrement()}>scoreを1減少するボタン</button>
    <input onChange={(e) => getArgs(e.target.value)}></input>
    </>
  );
}

さいごに

学習させていただいた先・ライブラリの公式ドキュメントです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0