redux持久化之redux-persist结合immutable使用问题

目录

前言

redux-persist

安装

使用到项目上

store.js

index.js

persist_reducer.js

immutable

安装

使用到项目上

count_reducer.js

函数组件

类组件

结合使用存在的问题

组件

persist-reducer.js

解决

组件

persist-reducer.js

解决思路

前言

最近学习了redux以及react-redux的结合使用确实让redux在react中更好的输出代码啦~

但是考虑到项目的各种需求,我们还是需要对redux进行深一步的改造,让其能更好的满足我们的日常开发,大大提高我们的开发效率。

今天给大家推荐两个好用的功能包,并解决一个它们结合使用存在的问题。

redux-persist

redux-persist 主要用于帮助我们实现redux的状态持久化

所谓状态持久化就是将状态与本地存储联系起来,达到刷新或者关闭重新打开后依然能得到保存的状态。

安装 yarn add redux-persist // 或者 npm i redux-persist

Github 地址 https://github.com/rt2zz/redux-persist

大家可以去看看官方的说明文档,这里就不一一介绍功能了,简单讲一点常用功能和导入到项目使用。

使用到项目上 store.js

带有 // ** 标识注释的就是需要安装后添加进去使用的一些配置,大家好好对比下投掷哦

下面文件也是一样

import { createStore, applyMiddleware, compose } from "redux"; import thunk from 'redux-thunk' import { persistStore, persistReducer } from 'redux-persist' // ** import storage from 'redux-persist/lib/storage' // ** import reducer from './reducer' const persistConfig = { // ** key: 'root',// 储存的标识名 storage, // 储存方式 whitelist: ['persistReducer'] //白名单 模块参与缓存 } const persistedReducer = persistReducer(persistConfig, reducer) // ** const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore(persistedReducer, composeEnhancers(applyMiddleware(thunk))) // ** const persistor = persistStore(store) // ** export { // ** store, persistor } index.js import React from 'react'; import ReactDOM from 'react-dom/client'; import { Provider } from 'react-redux' import { BrowserRouter } from 'react-router-dom' import { PersistGate } from 'redux-persist/integration/react' // ** import { store, persistor } from './store' // ** import 'antd/dist/antd.min.css'; import './index.css'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <Provider store={store}> {/* 使用PersistGate //** */} <PersistGate loading={null} persistor={persistor}> <BrowserRouter> <App /> </BrowserRouter> </PersistGate> </Provider> </React.StrictMode> ); persist_reducer.js

注意此时的模块是在白名单之内,这样persist_reducer的状态就会进行持久化处理了

import { DECREMENT } from './constant' const defaultState = ({ count: 1000, title: 'redux 持久化测试' }) const reducer = (preState = defaultState, actions) => { const { type, count } = actions switch (type) { case DECREMENT: return { ...preState, count: preState.count - count * 1 } default: return preState } } export default reducer

这样就可以使用起来了,更多的配置可以看看上面Github的地址上的说明文档

immutable

immutable 主要配合我们redux的状态来使用,因为reducer必须保证是一个纯函数,所以我们当状态中有引用类型的值时我们可能进行浅拷贝来处理,或者遇到深层次的引用类型嵌套时我们采用深拷贝来处理。

但是我们会觉得这样的处理确实稍微麻烦,而且我们若是采用简单的深拷贝 JSON.parse JSON.stringify 来处理也是不靠谱的,存在缺陷 就比如属性值为undefined 时会忽略该属性。

所以 immutable 就是来帮我们解决这些问题,使用它修改后会到的一个新的引用地址,且它并不是完全复制的,它会尽可能的利用到未修改的引用地址来进行复用,比起传统的深拷贝性能确实好很多。

这里就不多说了,想要了解更多可以看看下面的GitHub官网说明文档。

安装 npm install immutable // 或者 yarn add immutable

GitHub地址 https://github.com/immutable-js/immutable-js

使用到项目上 count_reducer.js import { INCREMENT } from './constant' import { Map } from 'immutable' // 简单的结构用Map就行 复杂使用fromJs 读取和设置都可以getIn setIn ... const defaultState = Map({ // ** count: 0, title: '计算求和案例' }) const reducer = (preState = defaultState, actions) => { const { type, count } = actions switch (type) { case INCREMENT: // return { ...preState, count: preState.count + count * 1 } return preState.set('count', preState.get('count') + count * 1) // ** default: return preState } } export default reducer

读取和派发如下 : 派发无需变化,就是取值时需要get

函数组件 const dispatch = useDispatch() const { count, title } = useSelector(state => ({ count: state.countReducer.get("count"), title: state.countReducer.get("title") }), shallowEqual) const handleAdd = () => { const { value } = inputRef.current dispatch(incrementAction(value)) } const handleAddAsync = () => { const { value } = inputRef.current dispatch(incrementAsyncAction(value, 2000)) } 类组件 class RedexTest extends Component { // ....略 render() { const { count, title } = this.props return ( <div> <h2>Redux-test:{title}</h2> <h3>count:{count}</h3> <input type="text" ref={r => this.inputRef = r} /> <button onClick={this.handleAdd}>+++</button> <button onClick={this.handleAddAsync}>asyncAdd</button> </div> ) } } //使用connect()()创建并暴露一个Count的容器组件 export default connect( state => ({ count: state.countReducer.get('count'), title: state.countReducer.get('title') }), { incrementAdd: incrementAction, incrementAsyncAdd: incrementAsyncAction } )(RedexTest)

这样就可以使用起来了,更多的配置可以看看上面Github的地址上的说明文档

结合使用存在的问题

结合使用有一个坑!!!

是这样的,当我们使用了redux-persist 它会每次对我们的状态保存到本地并返回给我们,但是如果使用了immutable进行处理,把默认状态改成一种它内部定制Map结构,此时我们再传给 redux-persist,它倒是不挑食能解析,但是它返回的结构变了,不再是之前那个Map结构了而是普通的对象,所以此时我们再在reducer操作它时就报错了

如下案例:

组件 import React, { memo } from "react"; import { useDispatch, useSelector, shallowEqual } from "react-redux"; import { incrementAdd } from "../store/persist_action"; const ReduxPersist = memo(() => { const dispatch = useDispatch(); const { count, title } = useSelector( ({ persistReducer }) => ({ count: persistReducer.get("count"), title: persistReducer.get("title"), }), shallowEqual ); return ( <div> <h2>ReduxPersist----{title}</h2> <h3>count:{count}</h3> <button onClick={(e) => dispatch(incrementAdd(10))}>-10</button> </div> ); }); export default ReduxPersist; persist-reducer.js import { DECREMENT } from './constant' import { fromJS } from 'immutable' const defaultState = fromJS({ count: 1000, title: 'redux 持久化测试' }) const reducer = (preState = defaultState, actions) =&gt; { const { type, count } = actions switch (type) { case DECREMENT: return preState.set('count', preState.get('count') - count * 1) default: return preState } } export default reducer

按理说是正常显示,但是呢由于该reducer是被redux-persist处理的,所以呢就报错了

报错提示我们没有这个 get 方法了,即表示变成了普通对象

解决 组件 import React, { memo } from "react"; import { useDispatch, useSelector, shallowEqual } from "react-redux"; import { incrementAdd } from "../store/persist_action"; const ReduxPersist = memo(() => { const dispatch = useDispatch(); // ** const { count, title } = useSelector( ({ persistReducer: { count, title } }) => ({ count, title, }), shallowEqual ); //const { count, title } = useSelector( // ({ persistReducer }) => ({ // count: persistReducer.get("count"), // title: persistReducer.get("title"), // }), // shallowEqual // ); return ( <div> <h2>ReduxPersist----{title}</h2> <h3>count:{count}</h3> <button onClick={(e) => dispatch(incrementAdd(10))}>-10</button> </div> ); }); export default ReduxPersist; persist-reducer.js import { DECREMENT } from './constant' import { fromJS } from 'immutable' const defaultState = ({ // ** count: 1000, title: 'redux 持久化测试' }) const reducer = (preState = defaultState, actions) => { const { type, count } = actions let mapObj = fromJS(preState) // ** switch (type) { case DECREMENT: // return preState.set('count', preState.get('count') - count * 1) return mapObj.set('count', mapObj.get('count') - count * 1).toJS() // ** default: return preState } } export default reducer 解决思路

由于 redux-persist 处理每次会返回普通对象,所以我们只能等要在reducer中处理状态时,我们先将其用immutable处理成它内部定制Map结构,然后我们再进行set操作修改,最后我们又将Map结构转换为普通对象输出,这样就完美的解决了这个问题。

以上就是redux持久化之redux-persist结合immutable使用问题的详细内容,更多关于redux持久化redux-persist的资料请关注易知道(ezd.cc)其它相关文章!

推荐阅读

    React-Redux是什么?

    React-Redux是什么?React-Redux是Redux的官方React绑定库,用于连接React和Redux的。它能够使你的React组件从Redux store中读取数据,并且向

    redux和react有啥区别?

    redux和react有啥区别?首先我们来看看什么是redux、react。reduxredux是一个JavaScript状态容器,主要提供状态管理。可以运行于服务端,客户

    react中redux是什么?

    react中redux是什么?下面本篇文章给大家介绍一下。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。redux是什么?Redux 是

    redux必须搭配react吗?

    redux必须搭配react吗?react中到底需不需要redux?下面本篇文章给大家介绍一下。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所

    redux如何关联react?

    redux如何关联react?Redux本身和React并没有之间的关联,它是一个通用Javscript App模块,用做App State的管理。要在React的项目中使用Redux

    react不用redux可以吗?

    react不用redux可以吗?答案是:可以。能不用redux就不用redux。下面给大家具体介绍一下。有一定的参考价值,有需要的朋友可以参考一下,希望对

    如何理解react-redux

    如何理解react-redux随着前端单页面开发越来越复杂,javascript需要管理越来越多的状态state。如果一个model的变化引起另一个model的变化

    如何在react中使用redux

    如何在react中使用redux目录结构Tips:与Redux无关的目录已省略
    |--src|-- store Redux目录|-- actions.js|-- index.js|

    为什么react需要redux?

    学 react 势必要学习 redux ,初学 redux 的时候,觉得 redux 很鸡肋,根据我的经验来看,我认为 redux 的设计非常的反设计原则,为什么这么说呢

    什么时候使用react-redux

    什么时候使用react-redux 需要使用redux的场景:● 用户的使用方式复杂● 不同身份的用户有不同的使用方式(比如普通用户和管理员)● 多

    什么是react-redux?

    redux是一个JavaScript状态容器,主要提供状态管理。可以运行于服务端,客户端,原生应用。除了支持React外还支持其他的UI框架,体积小,只有2kb

    React项目中使用Redux的react-redux

    React项目中使用Redux的react-redux目录背景UI 组件容器组件connect()mapStateToProps()mapDispatchToProps()组件实例:计数器背景
    在前

    ReactRedux使用配置详解

    ReactRedux使用配置详解目录前言redux三大原则redux执行流程redux具体使用执行流程redux使用流程前言
    在使用redux之前,首先了解一下redu

    使用react+redux实现弹出框案例

    使用react&#43;redux实现弹出框案例本文实例为大家分享了用react&#43;redux实现弹出框案例的具体代码,供大家参考,具体内容如下
    redux 实