React 之 redux-persist 持久化

前言

技术栈:

react + redux + react-redux + redux-persist
注:
1、react-redux 这里我有文章介绍:文章链接
2、如果是使用 redux-toolkit ,请看这篇文章链接

说明:

我这里结合redux的例子 todos 来的

1、安装

npm i redux-persist

官方文档:文档链接

2、使用

:有接触过 react-redux 的,看 2.1、2.2 就行

2.1 persistReducer 和 persistStore

src/store/index.js

import { createStore } from 'redux'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage';

import rootReducer from '../reducers'

// 配置对象
const persistConfig = {
    key: 'root',
    storage,
}

// 创建一个新的 Redux 状态 reducer
const persistedReducer = persistReducer(persistConfig, rootReducer)

let store = createStore(persistedReducer)
// 创建一个新的 Redux store
let persistor = persistStore(store)

const storePersistor = { store, persistor }
export default storePersistor;

2.2 使用 PersistGate 包装根组件

src/index.js

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


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={storePersistor.store}>
    {/* 使用 PersistGate 包装根组件,这会延迟应用 UI 的呈现,直到检索到持久化状态并将其保存到 redux 中 */}
    <PersistGate loading={null} persistor={storePersistor.persistor}>
        <App />
      </PersistGate>
  </ Provider>
);

src/App.js

import React from "react";
import AddTodo from "./containers/AddTodo";
import VisibleTodoList from "./containers/VisibleTodoList";


function App() {
  return (
    <div className="App">
      <AddTodo />
      <VisibleTodoList />
    </div>
  );
}

export default App;

2.3 Actions

src/actions/index.js

export const addTodo = (text) => {
    return {
        type: 'ADD_TODO',
        id: new Date().getTime(),
        text,
    }
}

2.4 Reducers

src/reducers/index.js

import { combineReducers } from 'redux'
import todos from './todos'

const todoApp = combineReducers({
    todos,
})

export default todoApp;

src/reducers/todos.js

const todos = (state = [], action) => {
    switch (action.type) {
        case 'ADD_TODO':
            return [
                ...state,
                {
                    id: action.id,
                    text: action.text
                }
            ]
        default:
            return state
    }
}
export default todos;

2.5 containers

/src/containers/AddTodo.js

import React, { createRef } from "react";
import { connect } from "react-redux"
import { addTodo } from '../actions/index'

const AddTodo = ({dispatch}) => {
    const inp = createRef()

    const add = () => {
        const val = inp.current.value;
        console.log('添加', val);
        dispatch(addTodo(val))
    }

    return (
        <div>
            <input ref={inp} />
            <button onClick={add}>Add Todo</button>
        </div>
    )
}

export default connect()(AddTodo);

src/containers/VisibleTodoList.js

import { connect } from 'react-redux';
import TodoList from '../components/TodoList';

const mapStateToProps = (state) => {
    return {
        todos: state.todos,
    }
}

const mapDispatchToProps = (dispatch) => {
    return {

    }
}

const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList);

export default VisibleTodoList;

2.6 components

src/components/TodoList.js

import React from "react";

const TodoList = ({ todos }) => {
    return (
        <div>
            {
                todos.map((todo, index) => {
                    return <li key={todo.id}>{todo.id}--{todo.text}</li>
                })
            }
        </div>
    )
}

export default TodoList;

3、State Reconciler 状态协调器

状态协调器定义如何将传入状态与初始状态合并

3.1 hardSet

选项的作用是强制将本地存储的值设置为 Redux 状态,而不是尝试合并它们,这可以确保在加载状态时,本地存储的值始终与 Redux 状态相匹配
举例说明:
传入状态: { foo: incomingFoo }
初始状态: { foo: initialFoo, bar: initialBar }
最终状态: { foo: incomingFoo } // 最终为传入的状态

import hardSet from 'redux-persist/lib/stateReconciler/hardSet'
 
const persistConfig = {
  key: 'root',
  storage,
  stateReconciler: hardSet,
}

3.2 autoMergeLevel1

这将自动合并一级深度。
举例:
传入状态: { foo: incomingFoo }
初始状态: { foo: initialFoo, bar: initialBar }
最终状态: { foo: incomingFoo, bar: initialBar } // 注意 incomingFoo 覆盖 initialFoo

3.3 autoMergeLevel2

这与 autoMergeLevel1 类似,只不过它浅层合并了两个级别
举例说明:
传入状态: { foo: incomingFoo }
初始状态: { foo: initialFoo, bar: initialBar }
最终状态:{ foo: mergedFoo, bar: initialBar } // 注意: { foo: mergedFoo, bar: initialBar } initialFoo 和 incomingFoo 是浅层合并的

4、Blacklist & Whitelist 黑名单和白名单

这里就用官方的例子:

// BLACKLIST
const persistConfig = {
  key: 'root',
  storage: storage,
  blacklist: ['navigation'] // navigation will not be persisted
};
 
// WHITELIST
const persistConfig = {
  key: 'root',
  storage: storage,
  whitelist: ['navigation'] // only navigation will be persisted
};

5、嵌套持久化

嵌套持久性可用于包含不同的存储适配器、代码拆分或深度筛选。例如,虽然黑名单和白名单只工作一个级别的深度,但我们可以使用嵌套的持久化来黑名单更深的值:

import { combineReducers } from 'redux'
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
 
import { authReducer, otherReducer } from './reducers'
 
const rootPersistConfig = {
  key: 'root',
  storage: storage,
  blacklist: ['auth']
}
 
const authPersistConfig = {
  key: 'auth',
  storage: storage,
  blacklist: ['somethingTemporary']
}
 
const rootReducer = combineReducers({
  auth: persistReducer(authPersistConfig, authReducer),
  other: otherReducer,
})
 
export default persistReducer(rootPersistConfig, rootReducer)

6、Storage Engines

localStorage

import storage from 'redux-persist/lib/storage'

sessionStorage

import storageSession from 'redux-persist/lib/storage/session'
  • 22
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值