💭

zustandの利用方法について紹介

に公開

Reactで状態管理を行う方法はいくつかありますが、軽量でシンプルな「Zustand」は注目されています。
本記事では、Zustandの概要と基本的な使い方、永続化の方法まで紹介します。

概要

ZustandはReact向けの軽量な状態管理ライブラリです。
主な特徴は以下の通りです。

  • シンプル: Reduxよりもコードが少なく済む
  • 高速: 不要な再レンダリングを最小限に
  • 柔軟: 状態の永続化やミドルウェア対応が容易
  • シェア率: Reactコミュニティで人気が高く、多くのプロジェクトで採用されている

https://zustand-demo.pmnd.rs/

Zastandの使い方

インストール

npm install zustand
# or
yarn add zustand

導入自体は、上記で完了できます。

Zastandのサンプル tabの切り替え

Zastandのサンプルとして、
tabの切り替えの実装を行います。

app/store/tabs.tsx

import { create } from "zustand"

/**
 * タブの状態を管理するストア
 */
export interface TabState {
  /** タブが開いているかどうか */
  activeTab: "test1" | "test2"
  /** タブを開く */
  changeActiveTab: (tab: "test1" | "test2") => void
}

/**
 * タブ状態管理ストア
 */
export const useTabStore = create<TabState>((set) => ({
  activeTab: "test1",

  changeActiveTab: (tab: "test1" | "ctest2") =>
    set({
      activeTab: tab,
    }),
}))

Storeでは、changeActiveTabを用意して、
test1とtest2でタブの切り替えを行っています。

app/about/page.tsx

"use client"

import { useTabStore } from "../stores/tabStore"

/**
 * タブ
 */
const About = () => {
  const { activeTab, changeActiveTab } = useTabStore()

  return (
    <div>
      {/* タブボタン */}
      <div className="tab-1" role="tablist">
        <label className={activeTab === "test1" ? "active" : ""}>
          <input type="radio" name="tab-1" onClick={() => changeActiveTab("test1")} />
          test1
        </label>
        <label className={activeTab === "test2" ? "active" : ""}>
          <input type="radio" name="tab-2" onClick={() => changeActiveTab("test2")} />
          test2
        </label>
      </div>

      {/* タブコンテンツ */}
      <div className="tab-content max_width">
        {activeTab === "test1" && (
          <div aria-labelledby="tabA">
            <h2 className="lower__subTitle">test1</h2>
          </div>
        )}
        {activeTab === "test2" && (
          <div aria-labelledby="tabB">
            <h2 className="lower__subTitle">test2</h2>
          </div>
        )}
      </div>
    </div>
  )
}

export default About

css

.tab-1 {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  max-width: 1200px;
  margin: 20px auto;
  label {
    flex: 1 1;
    order: -1;
    min-width: 100px;
    padding: 0.9em 1em 0.5em;
    font-size: 0.9em;
    font-weight: bold;
    color: #535353;
    text-align: center;
    cursor: pointer;
    background-color: #e9f0f6;
    border-bottom: 1px solid #f0f0f0;
    border-radius: 0;
  }
  label:hover {
    opacity: 0.8;
  }
  input {
    display: none;
  }
  div {
    display: none;
    width: 100%;
    padding: 1.5em 1em;
    background-color: $white;
  }
  .active {
    color: #333333;
    background-color: $white;
    border-color: $main-color #f0f0f0 $white;
    border-style: solid;
    border-width: 4px 1px 1px;
    border-radius: 5px;
  }

  .active + div {
    display: block;
  }
}

上記で、/aboutにアクセスすると、上手くタブの切り替えが設定できます。

tab切り替えのデザイン
https://pote-chil.com/css-stock/ja/tab#1

Zustandの永続化

現状のStoreだと、タブを閉じた場合やリロードした場合に、storeの情報が消えてしまいます。
もしZustandの状態の永続化したい場合は、zustand/middlewareのpersistを使用します。

import { create } from "zustand"
import { persist } from "zustand/middleware"

/**
 * タブの状態を管理するストア
 */
export interface TabState {
  /** タブが開いているかどうか */
  activeTab: "test1" | "test2"
  /** タブを開く */
  changeActiveTab: (tab: "test1" | "test2") => void
}

/**
 * タブ状態管理ストア
 */
export const useTabStore = create<TabState>()(
  persist(
    (set) => ({
      activeTab: "test1",
      changeActiveTab: (tab) => set({ activeTab: tab }),
    }),
    {
      name: "tab-storage", // localStorage に保存されるキー名
    },
  ),
)

上記で試すと、リロードしてもローカルストレージに保存されているため、
前回の状態を引き継ぐことができます。

まとめ

  • Zustandはシンプルで軽量なReact状態管理ライブラリ
  • persistを使えば状態を永続化できる
    Zustand を使うことで、シンプルで直感的な状態管理が実現できます。
    ぜひ使ってみてください。

Discussion