新手快速入门redux/toolkit

457 阅读3分钟

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的区别。

文件结构如下:

image.png

相关代码如下:

//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使用场景:

image.png

图中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;

页面如下:

image.png

下图为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;

页面:

image.png

总结:reduxJS/toolkit是对rendux的reducer、actions及store的创建做了封装,使用起来更为方便明了。欢迎大家多多指导。