本篇内容主要讲解“redux持久化之redux-persist怎么结合immutable使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“redux持久化之redux-persist怎么结合immutable使用”吧!
redux-persist 主要用于帮助我们实现redux的状态持久化
所谓状态持久化就是将状态与本地存储联系起来,达到刷新或者关闭重新打开后依然能得到保存的状态。
yarn add redux-persist
// 或者
npm i redux-persist
带有 // ** 标识注释的就是需要安装后添加进去使用的一些配置,大家好好对比下投掷哦
下面文件也是一样
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
}
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的状态就会进行持久化处理了
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 主要配合我们redux的状态来使用,因为reducer必须保证是一个纯函数,所以我们当状态中有引用类型的值时我们可能进行浅拷贝来处理,或者遇到深层次的引用类型嵌套时我们采用深拷贝来处理。
但是我们会觉得这样的处理确实稍微麻烦,而且我们若是采用简单的深拷贝 JSON.parse JSON.stringify 来处理也是不靠谱的,存在缺陷 就比如属性值为undefined 时会忽略该属性。
所以 immutable 就是来帮我们解决这些问题,使用它修改后会到的一个新的引用地址,且它并不是完全复制的,它会尽可能的利用到未修改的引用地址来进行复用,比起传统的深拷贝性能确实好很多。
npm install immutable
// 或者
yarn add immutable
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>
<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()()创建并暴露一个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>
<h3>ReduxPersist----{title}</h3>
<h4>count:{count}</h4>
<button onClick={(e) => dispatch(incrementAdd(10))}>-10</button>
</div>
);
});
export default ReduxPersist;
import { DECREMENT } from './constant'
import { fromJS } from 'immutable'
const defaultState = fromJS({
count: 1000,
title: 'redux 持久化测试'
})
const reducer = (preState = defaultState, actions) => {
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>
<h3>ReduxPersist----{title}</h3>
<h4>count:{count}</h4>
<button onClick={(e) => dispatch(incrementAdd(10))}>-10</button>
</div>
);
});
export default ReduxPersist;
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使用”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。