redux和ReduxJS/Toolkit状态管理简单对比
学习的最佳方法我个人觉得还是看官方文档比较权威: 中文官方文档、英文官方文档。
1. 什么是Redux Toolkit
[Redux Toolkit] 是redux官方推荐的编写 Redux 逻辑的方法。它包含了 Redux 核心,并包含我们认为对于构建 Redux 应用必不可少的软件包和功能。简化了大多数Redux任务,简化了大多数 Redux 任务,防止了常见错误,并使编写 Redux 应用程序更加容易。
为了方便后面内容,之后 Redux Toolkit 简称 RTK
2. 安装RTK相关包
npm install @reduxjs/toolkit react-redux
npm install react-redux
3.基础开发流程(实现一个全局loading)
- 创建一个store文件夹
- 创建一个index.ts作为主入口
- 创建一个slices文件夹,用来存放Slice
- 在slices文件夹里创建counterSlice.ts文件、创建globalSlice.ts文件
- 创建一个Reducer文件,在其下面创建index.ts 用来对比redux和 reduxjs/toolkit的区别。
文件结构如下:
相关代码如下:
//store/index.ts
import { configureStore } from "@reduxjs/toolkit";
import { counterReducers } from "./slices/counterSlice";
import { globalReducers } from "./slices/globalSlice";
//redux写法------start---------
// import { createStore } from "redux";
// import { counterReducer } from "./Reducer/index";
//createStore 创建一个redux数据(旧,测试用的,使用时忽略)
// const store = createStore(counterReducer);
//redux写法------end---------
// configureStore创建一个redux数据(新);
const store = configureStore({
//合并多个slice
reducer: {
counter: counterReducers,
globalData: globalReducers,
},
});
export default store;
//slices/counterSlice.ts
import { configureStore } from "@reduxjs/toolkit";
import { counterReducers } from "./slices/counterSlice";
import { globalReducers } from "./slices/globalSlice";
//redux写法------start---------
// import { createStore } from "redux";
// import { counterReducer } from "./Reducer/index";
//createStore 创建一个redux数据(旧,测试用的,使用时忽略)
// const store = createStore(counterReducer);
//redux写法------end---------
// configureStore创建一个redux数据(新);
const store = configureStore({
//合并多个slice
reducer: {
counter: counterReducers,
globalData: globalReducers,
},
});
export default store;
//slices/globalSlce.ts
import { createSlice } from "@reduxjs/toolkit";
interface GlobalData {
loading: boolean;
userInfo: object;
}
const initialState = {
loading: false, //控制全局loading
userInfo: {}, //存储用户登录信息
};
export const globalDataSlice = createSlice({
name: "globalData",
initialState,
reducers: {
setGlobalLoading: (state, { payload }) => {
state.loading = payload;
},
setUserInfo: (state, { payload }) => {
state.userInfo = payload.userInfo;
},
},
});
//actions
export const { setGlobalLoading } = globalDataSlice.actions;
//reducers
export const globalReducers = globalDataSlice.reducer;
//Reducer/index.ts
//该文件为测试 redux 旧写法创建,忽略,如有新reducer可在slices文件下创建
export const counterReducer = (state = { value: 0 }, action: any) => {
switch (action.type) {
case "counter/incremented":
return { value: state.value + 1 };
case "counter/decremented":
return { value: state.value - 1 };
default:
return state;
}
};
4.在入口文件引入store,共享数据
import { Provider } from "react-redux";
import store from "./store";
....
<Provider store={store}>
<ConfigProvider locale={zhCN}>
<BasicRoute />
</ConfigProvider>
</Provider>
5.添加到全局以后我们如何使用呢?如下图:
此图为reduxjs/toolkit使用场景:
图中loading是我全局封装的加载,可以忽略掉,(下期会有如何封装loading的方法)
相关代码如下:
下图为reduxjs/toolkit相关使用方式
import { useSelector, useDispatch } from "react-redux";
import { Button, Divider } from "antd";
import { decrease, increase, calculate } from "@/store/slices/counterSlice";
import { setGlobalLoading } from "@/store/slices/globalSlice";
import OldRedux from "./oldIndex";
const cls = "counter";
const Counter = () => {
const dispatch = useDispatch();
const { value, calculateValue, title } = useSelector((state: any) => {
return state.counter;
});
const loading = () => {
dispatch(setGlobalLoading(true));
setTimeout(() => {
dispatch(setGlobalLoading(false));
}, 3000);
};
//计算后的值
return (
<div className={cls}>
<Divider>基础用法({title})</Divider>
<h2>当前计算值:{value}</h2>
<Button onClick={() => dispatch(increase())}>+1</Button>
<Button onClick={() => dispatch(decrease())}>-1</Button>
<Divider>如何传参({title})</Divider>
<h2>当前计算值:{calculateValue}</h2>
<Button onClick={() => dispatch(calculate({ value: 2 }))}>+2</Button>
<Button onClick={() => dispatch(calculate({ value: -3 }))}>-3</Button>
<Divider>全局loading</Divider>
<Button onClick={() => loading()}>3秒后自动关闭全局loading</Button>
</div>
);
};
export default Counter;
页面如下:
下图为redux的调用方式:
首先,放开store/index.ts文件中的createStore相关代码:
import { configureStore } from "@reduxjs/toolkit";
import { counterReducers } from "./slices/counterSlice";
import { globalReducers } from "./slices/globalSlice";
//redux写法------start---------
import { createStore } from "redux";
import { counterReducer } from "./Reducer/index";
// createStore 创建一个redux数据(旧,测试用的,使用时忽略)
const store = createStore(counterReducer);
//redux写法------end---------
// configureStore创建一个redux数据(新);
// const store = configureStore({
// //合并多个slice
// reducer: {
// counter: counterReducers,
// globalData: globalReducers,
// },
// });
export default store;
使用方式(这里不做过多介绍了):
import { useSelector, useDispatch } from "react-redux";
// import { useState } from "react";
import { Button, Divider } from "antd";
// import store from "../../store";
const cls = "counter";
const Counter = () => {
const dispatch = useDispatch();
// const [oldState, setOldState] = useState({ value: 0 });
//新
const { value } = useSelector((state: any) => {
return state;
});
//旧
// store.subscribe(() => {
// console.log("=====", store.getState());
// setOldState(store.getState());
// });
//计算后的值
return (
<div className={cls}>
<Divider>旧redux</Divider>
<h2>当前计算值:{value}</h2>
<Button onClick={() => dispatch({ type: "counter/incremented" })}>
+1
</Button>
<Button onClick={() => dispatch({ type: "counter/decremented" })}>
-1
</Button>
</div>
);
};
export default Counter;
页面:
总结:reduxJS/toolkit是对rendux的reducer、actions及store的创建做了封装,使用起来更为方便明了。欢迎大家多多指导。