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?

redux-toolkitでローカルストレージにデータを永続化する方法

Last updated at Posted at 2024-12-27

データを永続化したい理由

ブラウザをリロードするとグローバルStateが初期化されたくないとき。
バックエンドを使う場合はセッションを使うけど、フロントエンドだけで実現したいときはローカルストレージに保存する。

ローカルストレージに直接データを保存することもできるけど、Reduxを使う場合はredux-persistを使うのが良い。

redux-persistのインストール

npm install redux-persist

storeの定義

store.ts
import { configureStore } from '@reduxjs/toolkit';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage'; // ローカルストレージを使用
import userSlice from './userSlice'; // ユーザーデータを管理するスライス

const persistConfig = {
  key: 'root', // ストレージに保存するキー
  storage,
};

const persistedReducer = persistReducer(persistConfig, userSlice.reducer);

const store = configureStore({
  reducer: {
    user: persistedReducer,
  },
});

const persistor = persistStore(store);

export { store, persistor };

Reduxプロバイダーを設定

redux-persistのPersistGateを使用して、ストアの再初期化が完了するまでUIを保留する。

App.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from './store';
import App from './App';

ReactDOM.render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>,
  document.getElementById('root')
);

useSliceの作成

ここは普通のSlice作成

useSlice.ts
import { createSlice } from '@reduxjs/toolkit';

const userSlice = createSlice({
  name: 'user',
  initialState: {
    userId: null,
  },
  reducers: {
    setUserId: (state, action) => {
      state.userId = action.payload;
    },
    clearUserId: (state) => {
      state.userId = null;
    },
  },
});

export const { setUserId, clearUserId } = userSlice.actions;
export default userSlice;

redux-persistとRedux-toolkitを一緒に使うと発生する可能性があるエラー

A non-serializable value was detected in an actionエラー

和訳するとアクションでシリアル化できない値が検出されましたであり、Reduxでシリアライズ不可なデータを使おうとするために発生するエラー

シリアライズ化とは

データ構造やオブジェクトを保存や送信が可能な形式(通常は文字列形式)に変換すること。

シリアライズ化できるデータ

  • プリミティブ型
  • オブジェクト
  • 配列

シリアライズ化できないデータ

  • 関数
  • 特殊なオブジェクト(Promise、Symbol、Map、Set)
  • クラスインスタンス

Reduxは関数やクラスインスタンス(シリアライズ不可データ)を使えないが、redux-persistはシリアライズ不可データをつかえる

Reduxはシリアライズ可能なデータのみを扱う設計になっているので、プリミティブ型やオブジェクト配列しか使えない。一方で、redux-persistはシリアライズ不可なデータ(関数やクラスインスタンス)も使える。

対応方法:Redux-toolkitのシリアライズデータチェックを除外する

Redux-toolkitのconfigureStoreで格納するデータがシリアライズできるかどうかをチェックしており、その設定をミドルウェアで制御できる。
redux-persist由来のアクションはシリアライズできるかどうかのチェックを除外する。

const persistedReducer = persistReducer(persistConfig, userReducer);

const store = configureStore({
  reducer: {
    flow: flowReducer,
    layout: layoutReducer,
    respondent: respondentReducer,
    user: persistedReducer,
    // user: userReducer,
  },
+  middleware: (getDefaultMiddleware) =>
+    getDefaultMiddleware({
+      serializableCheck: {
+        // 非シリアライズ可能な値を無視するための例外を指定
+        ignoredActions: [
+          "persist/PERSIST",
+        ],
+      },
    }),
});

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?