溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

redux持久化之redux-persist怎么結(jié)合immutable使用

發(fā)布時(shí)間:2022-08-18 09:23:42 來源:億速云 閱讀:191 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“redux持久化之redux-persist怎么結(jié)合immutable使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“redux持久化之redux-persist怎么結(jié)合immutable使用”吧!

redux-persist

redux-persist 主要用于幫助我們實(shí)現(xiàn)redux的狀態(tài)持久化

所謂狀態(tài)持久化就是將狀態(tài)與本地存儲(chǔ)聯(lián)系起來,達(dá)到刷新或者關(guān)閉重新打開后依然能得到保存的狀態(tài)。

安裝

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

使用到項(xiàng)目上

store.js

帶有 // ** 標(biāo)識(shí)注釋的就是需要安裝后添加進(jìn)去使用的一些配置,大家好好對(duì)比下投擲哦

下面文件也是一樣

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',// 儲(chǔ)存的標(biāo)識(shí)名
    storage, // 儲(chǔ)存方式
    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

注意此時(shí)的模塊是在白名單之內(nèi),這樣persist_reducer的狀態(tài)就會(huì)進(jìn)行持久化處理了

import { DECREMENT } from './constant'
const defaultState = ({
    count: 1000,
    title: 'redux 持久化測(cè)試'
})
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 主要配合我們r(jià)edux的狀態(tài)來使用,因?yàn)閞educer必須保證是一個(gè)純函數(shù),所以我們當(dāng)狀態(tài)中有引用類型的值時(shí)我們可能進(jìn)行淺拷貝來處理,或者遇到深層次的引用類型嵌套時(shí)我們采用深拷貝來處理。

但是我們會(huì)覺得這樣的處理確實(shí)稍微麻煩,而且我們?nèi)羰遣捎煤唵蔚纳羁截?JSON.parse JSON.stringify 來處理也是不靠譜的,存在缺陷 就比如屬性值為undefined 時(shí)會(huì)忽略該屬性。

所以 immutable 就是來幫我們解決這些問題,使用它修改后會(huì)到的一個(gè)新的引用地址,且它并不是完全復(fù)制的,它會(huì)盡可能的利用到未修改的引用地址來進(jìn)行復(fù)用,比起傳統(tǒng)的深拷貝性能確實(shí)好很多。

安裝

npm install immutable
// 或者
yarn add immutable

使用到項(xiàng)目上

count_reducer.js
import { INCREMENT } from './constant'
import { Map } from 'immutable'
// 簡單的結(jié)構(gòu)用Map就行 復(fù)雜使用fromJs 讀取和設(shè)置都可以getIn setIn ...
const defaultState = Map({ // **
    count: 0,
    title: '計(jì)算求和案例'
})
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

讀取和派發(fā)如下 : 派發(fā)無需變化,就是取值時(shí)需要get

函數(shù)組件

    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>
                <h3>Redux-test:{title}</h3>
                <h4>count:{count}</h4>
                <input type="text" ref={r => this.inputRef = r} />
                <button onClick={this.handleAdd}>+++</button>
                <button onClick={this.handleAddAsync}>asyncAdd</button>
            </div>
        )
    }
}
//使用connect()()創(chuàng)建并暴露一個(gè)Count的容器組件
export default connect(
    state => ({
        count: state.countReducer.get('count'),
        title: state.countReducer.get('title')
    }),
    {
        incrementAdd: incrementAction,
        incrementAsyncAdd: incrementAsyncAction
    }
)(RedexTest)

這樣就可以使用起來了,更多的配置可以看看上面Github的地址上的說明文檔

結(jié)合使用存在的問題

結(jié)合使用有一個(gè)坑?。?!

是這樣的,當(dāng)我們使用了redux-persist 它會(huì)每次對(duì)我們的狀態(tài)保存到本地并返回給我們,但是如果使用了immutable進(jìn)行處理,把默認(rèn)狀態(tài)改成一種它內(nèi)部定制Map結(jié)構(gòu),此時(shí)我們?cè)賯鹘o redux-persist,它倒是不挑食能解析,但是它返回的結(jié)構(gòu)變了,不再是之前那個(gè)Map結(jié)構(gòu)了而是普通的對(duì)象,所以此時(shí)我們?cè)僭趓educer操作它時(shí)就報(bào)錯(cuò)了

如下案例:

組件

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>
      <h3>ReduxPersist----{title}</h3>
      <h4>count:{count}</h4>
      <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 持久化測(cè)試'
})
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處理的,所以呢就報(bào)錯(cuò)了

redux持久化之redux-persist怎么結(jié)合immutable使用

報(bào)錯(cuò)提示我們沒有這個(gè) get 方法了,即表示變成了普通對(duì)象

解決

組件

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>
      <h3>ReduxPersist----{title}</h3>
      <h4>count:{count}</h4>
      <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 持久化測(cè)試'
})
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 處理每次會(huì)返回普通對(duì)象,所以我們只能等要在reducer中處理狀態(tài)時(shí),我們先將其用immutable處理成它內(nèi)部定制Map結(jié)構(gòu),然后我們?cè)龠M(jìn)行set操作修改,最后我們又將Map結(jié)構(gòu)轉(zhuǎn)換為普通對(duì)象輸出,這樣就完美的解決了這個(gè)問題。

到此,相信大家對(duì)“redux持久化之redux-persist怎么結(jié)合immutable使用”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI