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的资料请关注我们其它相关文章!

(0)

相关推荐

  • react18中react-redux状态管理的实现

    react的状态管理还是挺多的现在流行的有以下五种: Recoil MobX XState Redux Context 今天我们来讲一下react众多状态管理之一的redux,虽然这个我不太喜欢用,但是我觉得简单的状态管理谁都会,但是难的就是程序员的分水岭,所以今天来给大家讲一下redux. 下面我们来讲讲redux的优点: 可以在众多组件中传值,突破react单向数据流的限制 不仅支持react还支持vue等主流框架 当然是好用方便啦 接下来我们讲一下啥时候去使用他 在我们有好多组件,但是组件

  • react redux及redux持久化示例详解

    目录 一.react-redux 二.redux持久化 一.react-redux react-redux依赖于redux工作. 运行安装命令:npm i react-redux: 使用: 将Provider套在入口组件处,并且将自己的store传进去: import FilmRouter from './FilmRouter/index' import {Provider} from 'react-redux' import store from './FilmRouter/views/red

  • 手把手教会你使用redux的入门教程

    目录 Redux详解 Redux介绍 Redux有什么作用 如何在React中使用Redux 如何使用React-redux Redux详解 Redux介绍 Redux 是 JavaScript 应用的状态容器,提供可预测的状态管理. 在Redux中有3个原则 单一数据源 整个应用的State被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个Stroe中. State 是只读的 唯一改变State 的方法就是触发Actions,Actions是一个用于描

  • React通过redux-persist持久化数据存储的方法示例

    在React项目中,我们经常会通过redux以及react-redux来存储和管理全局数据.但是通过redux存储全局数据时,会有这么一个问题,如果用户刷新了网页,那么我们通过redux存储的全局数据就会被全部清空,比如登录信息等. 这个时候,我们就会有全局数据持久化存储的需求.首先我们想到的就是localStorage,localStorage是没有时间限制的数据存储,我们可以通过它来实现数据的持久化存储. 但是在我们已经使用redux来管理和存储全局数据的基础上,再去使用localStora

  • 详解在React-Native中持久化redux数据

    在最近的一个项目中,要求对 redux 数据做持久化处理,经过研究后成功实现,在此记录一下过程 我们可以使用 redux-persist 对数据做持久化处理 安装 npm i --save redux-persist 使用 安装成功后,我们需要对 store 代码进行修改,这是我的 store 生成文件 import {applyMiddleware, createStore, compose} from 'redux'; import {createLogger} from 'redux-lo

  • 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 Toolkit简化Redux

    了解Redux Toolkit,这是用于高效Redux开发的经过验证的工具集.在本文中,你将看到为什么Redux Toolkit值得React社区更多的关注. React和Redux被认为是大规模React应用中管理状态的最佳组合.然而,随着时间的推移,Redux的受欢迎程度下降,原因是: 配置Redux Store并不简单. 我们需要几个软件包来使Redux与React一起工作. Redux需要太多样板代码. 带着这些问题,Redux的创建者Dan Abramov发表了名为<你可能不需要Red

  • 在小程序中集成redux/immutable/thunk第三方库的方法

    一.前言 小程序给我们暴露了两个参数 require 和 module , require 用来在模块中加载其他模块, module 用来将模块中的方法暴露出去 module.exports = function(){} 所以只要需要让第三方库的代码使用这种形式的 export 就可以了 二.构建Redux的微信小程序包 打一个 Redux 包,让它可以兼容微信小城的加载方式 git clone https://github.com/reactjs/redux.git npm install #

  • Redux 和 Mobx的选择问题:让你不再困惑!

    我在去年大量的使用了 Redux,但我最近都在使用 Mobx 来做状态(state)管理.似乎现在社区里关于该选什么来替代 Redux 很自然地成为了一件困惑的事.开发者不确定该选择哪种解决方案.这个问题并不只是出现在 Redux 与 Mobx 上.无论何时,只要存在选择,人们就会好奇最好的解决问题的方式是什么.我现在写的这些是为了解决 Redux 和 Mobx 这两个状态管理库之间的困惑. 大部分的文章都用 React 来介绍 Mobx 和 Redux 的用法.但是在大部分情况下你都可以将 R

  • React Redux使用配置详解

    目录 前言 redux三大原则 redux执行流程 redux具体使用 执行流程 redux使用流程 前言 在使用redux之前,首先了解一下redux到底是什么? 用过vue的肯定知道vuex,vuex是vue中全局状态管理工具,主要是用于解决各个组件和页面之间数据共享问题,对数据采用集中式管理,而且可以通过插件实现数据持久化 redux跟vuex类似,最主要的就是用作状态的管理,redux用一个单独的常量状态state来保存整个应用的状态,可以把它想象成数据库,用来保存项目应用中的公共数据

  • React状态管理Redux原理与介绍

    目录 一.Redux 二.Redux的组成 2.1 store 2.2 state 2.3 action 2.4 reducer 三.三大原则 3.1 单一数据源 3.2 State只读 3.3 使用纯函数修改State 四.基于Redux的TodoList 五.react-redux 5.1 connect方法 5.2 Provider组件 一.Redux 和vuex一样,redux的出现是为了管理web应用的公共状态. 这些 state 可能包括服务器响应.缓存数据.本地生成尚未持久化到服务

  • React immer与Redux Toolkit使用教程详解

    目录 1. immer 1.1 setState结合immer使用 1.2 useState结合immer使用 1.3 immer和redux集合 2. Redux Toolkit 1. immer 概述: 它和immutable相似的,实现了操作对象的数据共享,可以优化性能.它实现的原理使用es6的Proxy完成的.小巧,没有像immutable哪样有新数据类型,而是使用js类型. 安装: yarn add immer@9 1.1 setState结合immer使用 简单使用: import

  • react redux入门示例

    环境准备 为了方便,这里使用create-react-app搭建react环境 create-react-app mydemo 弹出配置 如果需要自定义react的配置,需要运行下面的命令把配置文件弹出来. npm run eject 安装redux npm i redux --save 简单理解 redux简单用法就是通过它的store来订阅和发布信息. 通过subscribe来订阅action,通过dispatch来触发action.reducer中定义来各个action要做的事情. dem

  • Taro集成Redux快速上手的方法示例

    前言的前言 最近被一款来自京东凹凸实验室的多终端开发框架Taro吸粉了,官方对 Taro 的简介是使用React语法,一键生成多终端应用(包括小程序 / H5 / 快应用 / RN 等),而目前 Github 的 Star 也达到了非常可观的数量:4k+.对此,笔者也尝了把鲜,体验了下如何使用Taro写微信小程序.感觉还是十分灵活易用(一气呵成,都没遇到bug!),并且 Taro 还集成了 Redux,解决了小程序没有数据流框架的痛点. 这里贴一个 Taro 的官方文档,有兴趣的同行们可以了解下

随机推荐