はじめに
React Reduxを使ってみる - BLOGで、クリック数をカウントするアプリを作りました。
しかし、ページを再読み込みするとカウントが0に戻ってしまっていたので
Redux Persistを使ってデータを永続化してみます。
Redux Persist
Reduxのストアのデータをローカルストレージに保存する。
※ローカルストレージ
HTMLでサポートされている、Webローカル環境に値を保存する機能
それぞれの値にキーをつけて保存し、いつでもキーを使って値を取得できる。
インストール
npm install --save redux-persist
Redux Persistを実装する
Redux Persistでは、通常のReducerとstoreに永続化のための
機能を組み込んだpersistReducerとpersistorを作成する。
- メッセージとカウントを表示する
- クリック時はカウントを+1して"INCREMENT"と表示する
- shuft+クリックでカウントを0にリセットして"RESET"と表示する
index.js
import React from "react"; import ReactDOM from "react-dom"; import { createStore } from "redux"; import { Provider } from "react-redux"; import { persistStore, persistReducer } from "redux-persist"; import storage from "redux-persist/lib/storage"; import { PersistGate } from "redux-persist/integration/react"; import App from "./components/App"; // ステートの値 let state_value = { counter: 0, message: "COUNTER" }; // レデューサー function countReducer(state = state_value, action) { switch (action.type) { case "INCREMENT": return { counter: state.counter + 1, message: "INCREMENT" }; case "RESET": return { counter: 0, message: "RESET" }; default: return state; } } // Redux Persistの設定 const config = { key: "root", storage: storage }; // パーシストレデューサーの作成 const persistedReducer = persistReducer(config, countReducer); // ストア、パーシスターの作成 let store = createStore(persistedReducer); let persistor = persistStore(store); // 表示をレンダリング ReactDOM.render( <Provider store={store}> <PersistGate loading={<p>now loading...</p>} persistor={persistor}> <App /> </PersistGate> </Provider>, document.getElementById("root") );
使用オブジェクトのインポート
import { persistStore, persistReducer } from "redux-persist"; import storage from "redux-persist/lib/storage"; import { PersistGate } from "redux-persist/integration/react";
Redux Persistの設定
Redux Persistの設定情報を値として用意する。
key : 任意の文字列。データ保存用の識別キー
storage : データ保存先の種類
const config = { key: "root", storage: storage };
persistReducerの作成
引数に先ほど設定した値と使用するReducerを指定して
persistReducerを作成する。
const persistedReducer = persistReducer(config, countReducer);
store, persistorの作成
まず通常のstoreをpersistedReducerを引数にして作成し
それを元にpersistStoreでpersistorを作成する。
let store = createStore(persistedReducer); let persistor = persistStore(store);
PersistGate
データの読み書きが完了してからコンポーネント類を表示するように調整
表示するコンポーネントをラップして使用する。
Reduxを使う場合のProviderコンポーネントの中にPersistGateを用意する
loading : 値のローディング中の表示
persistor : 作成したpersistorを指定する
ReactDOM.render( <Provider store={store}> <PersistGate loading={<p>now loading...</p>} persistor={persistor}> <App /> </PersistGate> </Provider>, document.getElementById("root") );
App.js
import React from "react"; import { connect } from "react-redux"; import Message from "./Message"; import Button from "./Button"; class App extends React.Component { render() { return ( <div> <h1>Redux Persist</h1> <Message /> <Button /> </div> ); } } export default connect()(App);
Message.js
import React from "react"; import { connect } from "react-redux"; class Message extends React.Component { render() { return ( <p> {this.props.message}: {this.props.counter} </p> ); } } export default connect(state => state)(Message);
Button.js
import React from "react"; import { connect } from "react-redux"; class Button extends React.Component { constructor(props) { super(props); this.doAction = this.doAction.bind(this); } doAction(e) { if (e.shiftKey) { this.props.dispatch({ type: "RESET" }); } else { this.props.dispatch({ type: "INCREMENT" }); } } render() { return ( <button onClick={this.doAction}> click </button> ); } } export default connect()(Button);