0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ReduxToolkitのstateを永続化する

Last updated at Posted at 2022-06-09

ReduxToolkitの値を永続化したい(๑╹ω╹๑ )

小難しく言うてますが、端的に言うとリロードしても消えないようにしたいということです。

reduxtoolkit-永続化.gif

( +ボタンを押した後、リロードしても数字がリセットされません )

すばらしいですね。
これができれば、サーバサイドから取得した値を再リロード後、いちいちもう一回サーバサイドへ取得しに行く必要がなくなります。

では、Let's ハンズオン!!

環境構築

今回のスキルスタックは以下になります。

  1. React
  2. TypeScript
  3. ReduxToolkit

とにかくシンプルです。
コードの全貌はこちらに置いておきます。

では、以下のコマンドを実行しましょう!

create-react-app localstorage-redux --template redux-typescript

このコマンドを実行して、HappyHacking!!と祈ってもらえれば作業開始です。

では、完了したら以下コマンドでアプリを開始させてください。

npm start

こんな画面になりましたか?

スクリーンショット 2022-06-09 22.06.46.png

では、コードを見ていきましょう。

実装

まずは、Store内のReduxのstateを永続化するためのライブラリをインストールしましょう!
今回はredux-persistというライブラリを使用します。

npm install redux-persist

次にsrc/app/store.tsを追記していきます。

こんな感じにしてみてください。

src/app/store.ts
import { Action, configureStore, ThunkAction } from '@reduxjs/toolkit';
import { combineReducers } from "redux";
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import thunk from 'redux-thunk';
import counterReducer from '../features/counter/counterSlice';

const reducers = combineReducers({
 counter: counterReducer,
});

const persistConfig = {
    key: 'root',
    storage
};

const persistedReducer = persistReducer(persistConfig, reducers);

const store = configureStore({
    reducer: persistedReducer,
    middleware: [thunk]
});

export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  RootState,
  unknown,
  Action<string>
>;

export default store;

そして、src/index.tsxがエラーでてると思うので、改修。
React18で書いておきますね。

src/index.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import { persistStore } from 'redux-persist';
import { PersistGate } from 'redux-persist/integration/react';
import App from './App';
import store from './app/store';
import './index.css';
import reportWebVitals from './reportWebVitals';

let persistor = persistStore(store);

const container = document.getElementById('root')!;
const root = createRoot(container);

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <App />
      </PersistGate>
    </Provider>
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

そして、src/features/counter/Counter.tsxの不要箇所を削除

src/features/counter/Counter.tsx
import React, { useState } from 'react';
import { useAppDispatch, useAppSelector } from '../../app/hooks';
import styles from './Counter.module.css';
import {
  decrement,
  increment,
  incrementByAmount,
  selectCount,
} from './counterSlice';

export function Counter() {
  const count = useAppSelector(selectCount);
  const dispatch = useAppDispatch();
  const [incrementAmount, setIncrementAmount] = useState('2');

  const incrementValue = Number(incrementAmount) || 0;

  return (
    <div>
      <div className={styles.row}>
        <button
          className={styles.button}
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}
        >
          -
        </button>
        <span className={styles.value}>{count}</span>
        <button
          className={styles.button}
          aria-label="Increment value"
          onClick={() => dispatch(increment())}
        >
          +
        </button>
      </div>
      <div className={styles.row}>
        <input
          className={styles.textbox}
          aria-label="Set increment amount"
          value={incrementAmount}
          onChange={(e) => setIncrementAmount(e.target.value)}
        />
        <button
          className={styles.button}
          onClick={() => dispatch(incrementByAmount(incrementValue))}
        >
          Add Amount
        </button>
      </div>
    </div>
  );
}

これで、再度npm startしてみるとこんな画面になります。

スクリーンショット 2022-06-09 22.17.08.png

プラスボタンを連打してみてください。

スクリーンショット 2022-06-09 22.18.36.png

そして、ブラウザを再リロード!

スクリーンショット 2022-06-09 22.19.05.png

5 がめでたくそのまま残りましたね。

これでReduxToolkitのstate永続化が完了です!

お疲れ様でした。

0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?