Next.js で React状態管理ライブラリの Zustand を使ってみる
Reactの状態管理ライブラリはいくつか存在します。
今回はそのうちの1つの「Zustand」を紹介していきたいと思います。
Reactにおける状態管理とは
まず冒頭出た、Reactの状態管理ってなんなの?という話です。
私はめっぽう説明が下手くそなので、某先生を呼んできました。
※ChatGPT先生にお礼は言いましょうね。
このような回答が返ってきました。
先生のおっしゃる通りで、Reactには2種類の状態管理があり、
ローカルな状態管理の代表例として、useStateがあります。
対してグローバルな状態管理の代表例として、Reduxが挙げられます。
Zustandは後者のグローバルな状態管理ライブラリとして利用されます。
つまり、Reduxは競合にあたります。
先生も言及されていますが、このような状態管理のライブラリは非常に便利な半面、
規模の大きいプロジェクトになればなるほど肥大化し、結果として扱いが困難になってしまう可能性がありますので、
適切なルールに基づいた管理が求められると言えます。
主な状態管理ライブラリ
前述の Redux 以外にも Recoil、Jotai など、React の状態管理ライブラリは多く存在します。
状態管理一つにしても、これだけの量のライブラリがあるということは驚きでした。
状態管理ライブラリについては、↓こちらの記事がすごく参考になりました。
Zustandについて
本題の Zustand についてです。
トレンドには乗ってきており、伸びているのがわかりますね。
使ってみる
実際にTodoアプリケーションで作ってみる。
Storeの作成
todo をため込む配列、todo を追加する addTodo、todo を削除する removeTodo を用意しました。
todo の状態を常に Store が管理してくれます。
store の書き方はとても簡単なので、Guthub を見ながらやってみてください。
import { create, useStore } from "zustand";
type TodoStore = {
todos: string[];
addTodo: (todo: string) => void;
removeTodo: (todo: string) => void;
};
export const useTodoStore = create<TodoStore>((set) => ({
todos: [],
addTodo: (todo) => set((state) => ({ todos: [...state.todos, todo] })),
removeTodo: (todo) => set((state) => ({ todos: state.todos.filter((t) => t !== todo) })),
}));
雑にひな型を作成
アイコンは Fontawesome、コンポーネントは mantine を使いました。
※めちゃくちゃ雑なのは無視で・・
const TodoLists = () => {
const todos = [
"ごみ捨て",
"洗濯",
"買い物"
];
const rows = todos.map((todo) => (
<tr key={todo}>
<td>{todo}</td>
<td><Button leftIcon={<FontAwesomeIcon icon={faTrash}/>}>削除する</Button></td>
</tr>
));
return (
<Table sx={{width: 500}}>
<thead>
<tr>
<th>Todoリスト</th>
<th>削除</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</Table>
);
}
const Page = () => {
const form = useForm({ initialValues: { todo: "" } });
return (
<Box>
<Title >Todoリスト</Title>
<Box sx={{display: "flex", marginBottom: 50}}>
<TextInput onChange={(e) => form.setFieldValue("todo", e.target.value)}></TextInput>
<Button>TODOにする</Button>
</Box>
<TodoLists/>
</Box>
)
}
こんな感じで、お洒落なTodoリストが出来上がりました。
Store は適用していないので全く動きません。
Storeを適用する
前述した、todo、addTodo、removeTodo を使って以下のように記述していきます。
const TodoLists = () => {
const {todos, removeTodo} = useTodoStore();
const rows = todos.map((todo) => (
<tr key={todo}>
<td>{todo}</td>
<td><Button onClick={() => removeTodo(todo)} leftIcon={<FontAwesomeIcon icon={faTrash}/>}>削除する</Button></td>
</tr>
));
return (
<Table sx={{width: 500}}>
<thead>
<tr>
<th>Todoリスト</th>
<th>削除</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</Table>
);
}
const Page = () => {
const {addTodo} = useTodoStore();
const form = useForm({ initialValues: { todo: "" } });
return (
<Box>
<Title >Todoリスト</Title>
<Box sx={{display: "flex", marginBottom: 50}}>
<TextInput onChange={(e) => form.setFieldValue("todo", e.target.value)}></TextInput>
<Button onClick={() => addTodo(form.values.todo)}>TODOにする</Button>
</Box>
<TodoLists/>
</Box>
)
}
ここまで完了すると以下のように Todo が作成されます。
当然、コンポーネントでStoreを管理しているわけではないので、別のコンポーネントだったり、ページだったりで呼び出すことも可能です。非常に便利。
おわりに
チョー簡単に Zustand 解説、やってみた系してみました。
皆さんもぜひ、Zustand 使って、Reactをどんどん便利にしていきましょう!(ただし、使うのであれば厳重に管理すること!)
では。
Discussion