0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React】 Zustand LocalStorage から自動でメモリに保管する方法

Posted at

はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。

React でアプリを作成するとき、リロードしても状態を保持したいことはありませんか?
例えば、

  • ログイン状態
  • ダークモード設定
  • カートの中身

など、毎回 API を叩かなくても良い状態は ブラウザの LocalStorage に保存すると便利です。

Zustand には、この処理を **自動化する仕組み(persist ミドルウェア)**が用意されています。今回はその使い方を解説します。


前提環境

  • React + Vite または CRA
  • TypeScript 使用
  • Zustand インストール済み
npm install zustand

persist ミドルウェアとは?

zustand/middleware に含まれる persist は、以下を自動で行います。

  • Zustand の状態を LocalStorage に保存
  • ページリロード時に LocalStorage から復元
  • 保存するキー名や内容をカスタマイズ可能

基本実装例

1. カウンターの状態を保存する例

import { create } from 'zustand';
import { persist } from 'zustand/middleware';

type CounterState = {
  count: number;
  increment: () => void;
  reset: () => void;
};

export const useCounterStore = create<CounterState>()(
  persist(
    (set) => ({
      count: 0,
      increment: () => set((state) => ({ count: state.count + 1 })),
      reset: () => set({ count: 0 }),
    }),
    {
      name: 'counter-storage', // LocalStorage に保存するキー名
    }
  )
);

2. コンポーネントで利用する

import { useCounterStore } from './stores/counterStore';

export const Counter = () => {
  const { count, increment, reset } = useCounterStore();

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+1</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
};

ポイント:

  • useCounterStore を呼び出すだけで LocalStorage への保存・復元が自動で行われます
  • 保存されたデータは Application > Local Storage で確認可能

保存するデータを一部だけに絞る

partialize オプションを使うと、状態の一部だけを保存できます。

persist(
  (set) => ({
    count: 0,
    tempValue: 'not persisted',
    increment: () => set((state) => ({ count: state.count + 1 })),
  }),
  {
    name: 'counter-storage',
    partialize: (state) => ({ count: state.count }), // count だけ保存
  }
);

保存先を LocalStorage → sessionStorage に変更

storage オプションで保存先を切り替えられます。

persist(
  (set) => ({
    count: 0,
    increment: () => set((state) => ({ count: state.count + 1 })),
  }),
  {
    name: 'counter-storage',
    storage: () => sessionStorage, // sessionStorage に保存
  }
);

セキュリティ注意点

LocalStorage は便利ですが、XSS 攻撃に弱いため、アクセストークンや重要情報の保存には注意が必要です。

  • 保存する情報は必要最小限にする
  • CSP(Content Security Policy)でスクリプトの挿入を防ぐ
  • 可能であれば HttpOnly Cookie を利用する

詳細は前回の記事の「SPA の XSS と CSRF 対策」でまとめています


まとめ

  • persist ミドルウェアを使うと、状態を LocalStorage に自動保存&復元
  • name でキー名指定、partialize で保存対象を絞れる
  • 保存先を sessionStorage に切り替えることも可能
  • セキュリティ対策(XSS 対策)を必ず考慮する

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?