この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは。データアナリティクス事業本部 サービスソリューション部の北川です。
Zustandとは
ZustandはReactの状態管理ライブラリの一つです。シンプルで使いやすく、他の状態管理ライブラリと比べてもコード量が少ないです。
基本的な使い方については、以下のエントリで書いています。
今回は、Zustandのミドルウェアを使ってみました。基本的には、公式のGitHubに沿って進めています。
Next.jsプロジェクトを作成
前回、エントリで使用したコードをそのまま使っていきます。
$ npx create-next-app sample-zustand --ts
$ yarn add zustand
// または
$ npm install zustand
libs/index.ts
import create from "zustand";
type Count = {
count: number;
increaseCount: () => void;
resetCount: () => void;
}
export const useStore = create<Count>((set) => ({
count: 0,
increaseCount: () =>
set((state) => {
return { count: state.count + 1 };
}),
resetCount: () => set({ count: 0 }),
}));
index.ts
import type { NextPage } from "next";
import { useStore } from "../libs/store";
import styles from "../styles/Home.module.css";
const Count = () => {
const count = useStore((state) => state.count);
console.log(count);
return (
<>
<h2>count: {count}</h2>
</>
);
};
const IncreaseCountButton = () => {
const increaseCount = useStore((state) => state.increaseCount);
return <button onClick={() => increaseCount()}>Increase</button>;
};
const ResetButton = () => {
const { resetCount } = useStore();
return <button onClick={() => resetCount()}>Reset</button>;
};
const Home: NextPage = () => {
return (
<div className={styles.container}>
<main className={styles.main}>
<Count />
<IncreaseCountButton />
<ResetButton />
</main>
</div>
);
};
export default Home;
ミドルウェアを試してみる
Zustandが用意しているいくつかのミドルウェアは、"zustand/middleware"
からインポートすることで使用できます。
devTools
devToolsミドルウェアを使用すると、拡張機能のRedux DevToolsを使えるようになります。 Redux DevToolsに関しては、こちらのエントリで書いています。
set
の第3引数に、それぞれのactionTypeを渡すことができます。
libs/index.ts
import create from "zustand";
import { devtools } from "zustand/middleware";
type Count = {
count: number;
increaseCount: () => void;
resetCount: () => void;
};
export const useStore = create<Count>()(
devtools((set) => ({
count: 0,
increaseCount: () =>
set(
(state: { count: number }) => {
return { count: state.count + 1 };
},
false,
"increaseCount"
),
resetCount: () => set({ count: 0 }, false, "resetCount"),
}))
);
immer
immerはオブジェクトをイミュータブルに扱うためのライブラリになります。
developersIOでも、以下のエントリが投稿されています。
immerミドルウェアを使用すると、push()やunshift()などの破壊的なメソッドを使用したstateの変更ができるようになります。このミドルウェアは、"zustand/middleware/immer"
からインストールします。
こちらは、公式のimmerミドルウェアを使ったコードです。
import create from 'zustand'
import { immer } from 'zustand/middleware/immer'
const useBeeStore = create(
immer((set) => ({
bees: 0,
addBees: (by) =>
set((state) => {
state.bees += by
}),
}))
)
自作ミドルウェア
提供されているミドルウェアではなく、自作のミドルウェアも作成できます。Zustandのデモでは、stateの変更を記録し、ログとして出力するミドルウェアを定義しています。
libs/index.ts
import create from "zustand";
type Count = {
count: number;
increaseCount: () => void;
resetCount: () => void;
};
const log = (config) => (set, get, api) =>
config(
(...args) => {
console.log(" applying", args);
set(...args);
console.log(" new state", get());
},
get,
api
);
export const useStore = create<Count>()(
log((set) => ({
count: 0,
increaseCount: () =>
set((state: { count: number }) => {
return { count: state.count + 1 };
}),
resetCount: () => set({ count: 0 }),
}))
);
複数ミドルウェアを使う
もちろん、以下のように記述することで、複数のミドルウェアを使用できます。
export const useStore = create<Count>()(
log(
devtools((set) => ({
count: 0,
increaseCount: () =>
set(
(state: { count: number }) => {
return { count: state.count++ };
},
false,
"increaseCount"
),
resetCount: () => set({ count: 0 }, false, "resetCount"),
}))
)
);
まとめ
今回は、Zustandのミドルウェアを簡単にですが、試してみました。Zustaindでは他にも、再現が難しかったのですが、stateの状態を保持するPersistミドルウェアなどもあります。
ミドルウェアは学ぶことが多くまだまだ勉強中です。これからもインプット、アウトプットに力を入れていきたいと思います。
ではまた。