redux官网:redux.js.org/
使用
安装
Redux Toolkit 包含了 Redux 核心,以及我们认为对于构建 Redux 应用程序必不可少的其他关键软件包(例如 Redux Thunk 和 Reselect)。
npm install @reduxjs/toolkit
npm install react-redux
npm install --save-dev redux-devtools
配置
在根目录下创建features文件夹,比如存储计数功能,就再创建一个couter文件夹,里面编写计数方法counterSlice文件:
couterSlice.js文件
import { createSlice } from '@reduxjs/toolkit';
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
// Redux Toolkit 允许我们在 reducers 写 "可变" 逻辑。它
// 并不是真正的改变状态值,因为它使用了 Immer 库
// 可以检测到“草稿状态“ 的变化并且基于这些变化生产全新的
// 不可变的状态
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
// 每个 case reducer 函数会生成对应的 Action creators
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
在根目录下创建app文件夹,里面再创建一个store的js文件,导入刚刚的couter桶。
store.js文件
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
export default configureStore({
reducer: {
// (createSlice的name) : (name + createSlice的export default .点后面)
counter: counterReducer,
},
});
在couter文件夹下创建couter文件,在里面用useSelector获取couter桶内数据。
couter.js文件(具体情况具体创建使用)
// redux_demo
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { decrement, increment } from './counterSlice';
// import styles from './Counter.module.css';
export function Counter() {
//useSelector()钩子获取桶内数据
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<div style={{ position: 'absolute', top: '50%', left: '50%' }}>
<div>
<button
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
Increment
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
Decrement
</button>
</div>
</div>
);
}
因为 Redux 的数据存储是通过使用一个全局的状态树来管理应用程序的状态。 这个状态树是一个不可变的对象,通过 Redux 提供的函数来修改。所有的组件都可以从状态树中获取数据,并目当状态发生改变时,组件会自动更新。Redux的数据存储是在内存中进行的,数据的读取和写入速度非常快。相比之下,本地存储是指将数据存储在浏览器的本地存储中,比如使用 localStorage或sessionStorage¹。Redux 的核心是一个store 对象,它里面包含着我们所储存的所有状态,类似一个物流中心,我们可以往里面存放数据,也可以从里面取出数据。Redux桶内数据刷新后就没有了。 所以我们需要对它做一个持久化存储。
redux-persist官网:redux-toolkit.js.org/rtk-query/u…
github:github.com/rt2zz/redux…
安装
npm install redux-persist
使用
针对多个reducer持久化存储方案:
在根目录下的app文件夹里面的store文件里:
import { configureStore } from '@reduxjs/toolkit';
import storage from 'redux-persist/lib/storage'; // defaults to localStorage for web
import { persistReducer, persistStore } from 'redux-persist';
import { combineReducers } from 'redux';
// 多个reducer,比如:counterReducer、listReducer、listProjectReducer
import counterReducer from '../features/counter/counterSlice';
import listReducer from '../features/dashboard/listSlice';
import listProjectReducer from '../features/projects/listSilce';
//使用 combineReducers 将所有的 reducer 组合起来。
const rootReducer = combineReducers({
counter: counterReducer,
list: listReducer,
listProject: listProjectReducer,
// 其他的 reducer 可以继续添加
});
// 配置持久化
const persistConfig = {
key: 'root',
storage,
// 你可以使用白名单或黑名单来指定哪些 reducer 需要持久化
whitelist: ['counter', 'list', 'listProject'], // 只有这两个 reducer 会被持久化
// blacklist: ['someOtherReducer'], // 不持久化的 reducer
};
// 创建持久化的 reducer
const persistedReducer = persistReducer(persistConfig, rootReducer);
// 创建 Redux store
const store = configureStore({
reducer: persistedReducer,
});
export const persistor = persistStore(store);
export default store;
tips:
- 白名单和黑名单:你可以通过
whitelist和blacklist配置选项来决定哪些 reducer 的状态需要持久化。使用白名单时,只持久化白名单中的 reducer;使用黑名单时,不持久化黑名单中的 reducer。 - 持久化存储:
redux-persist默认使用localStorage。如果你需要使用其他存储(如sessionStorage),可以在persistConfig中更改storage配置。
在根目录下的index文件里:
import React from 'react';
import ReactDOM from 'react-dom/client';
import 'reset-css';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import store, { persistor } from './app/store';
import App from './App';
//在你的应用入口文件中,使用 `PersistGate` 来包裹你的应用,这样在状态恢复之前,UI 不会渲染
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<React.StrictMode>
<App />
</React.StrictMode>
</PersistGate>
</Provider>
);
现在,就可以在localstorage里面查看存储的数据:
这时可能会有一个报错store.js:50 A non-serializable value was detected in an action, in the path: register. Value: ƒ register(key) { _pStore.dispatch({ type: _constants__WEBPACK_IMPORTED_MODULE_0__.REGISTER, key: key }); } Take a look at the logic that dispatched this action: {type: 'persist/PERSIST', register: ƒ, rehydrate: ƒ}……
它表示这是非序列化的数据,所以报错。 这时你可以在persistConfig里面添加以下代码以关闭redux序列化检测:
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}),