はじめに
この記事は zustand の使い方の 備忘録 です。
zustandとは
かなり シンプル に使える グローバル状態管理ライブラリ です。
インストール
npm install zustand
最速で Global state を定義する
Global state は create関数 に 第1引数 が set・第2引数 が get で
戻り値 が オブジェクト の callback関数 を渡すことで作成します。
戻り値のオブジェクト に Global state を 記述 していきます。
オブジェクト内に state を プロパティ として 記述 し
更新関数 を メソッド として 記述 します。
更新関数 の中では set の引数に state名と更新したい値 の オブジェクト を渡します。
下記が 簡単な実装例 です。
"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 を取得出来ます。
下記に 実装例 を示します。
"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引数 を
上手く使うことでも 実装 出来ます。
下記に 実装例 を示します。
"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 は実行された時にコンポーネントの再描画が 発生しない ので
こちらを使う方がパフォーマンスが良い です。
パフォーマンスが良い方法 の実装例を下記に示します。
"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>
</>
);
}
パフォーマンスの良い方法 で 分割代入 する 実装例 を示します。
"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 を渡します。
追記:更新関数に渡された引数を更新関数の中で使う
入力された値を コンソールに出力 することで 更新関数に渡された引数 を 更新関数の中 で
使う例を下記に示します。
"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>
</>
);
}
さいごに
学習させていただいた先・ライブラリの公式ドキュメントです。