React中如何使用Redux(二)

127 阅读3分钟

认识Redux Toolkit

Redux Toolkit 是 Redux 官方强烈推荐,开箱即用的一个高效的 Redux 开发工具集。

在前面我们学习Redux的时候发现,Redux的编写逻辑还是有点复杂和繁琐的,分别在不同的文件中定义actioncreators和reducer,配置store的增强等;Redux Toolkit可以简化最常见场景下的 Redux 开发,包括配置 store、定义 reducer等。

在很多地方为了称呼方便,我们也将它称为 "RTK";

Redux Toolkit最初是为了帮助解决有关Redux的三个常见问题而创建的:

  • 配置Redux store过于复杂
  • 必须添加很多软件包才能开始使用Redux
  • Redux有太多样板代码

安装redux toolkit:

npm install @reduxjs/toolkit react-redux

redux toolkit的核心api主要是下面几个:

  • configureStore():封装了createStore,简化配置,提供一些现成的默认配置项。它可以自动组合slice的reducer,可以添加任何Redux中间件,默认情况下包含redux-thunk,并开启了Redux DevTools扩展。
  • createSlice():接受reducer函数的对象、切片名称和初始状态值,并自动生成切片reducer,并带有相应的actions。
  • createAsyncThunk():接受一个动作类型字符串和一个返回值为 promise 的函数, 并生成一个 thunk 函数,这个 thunk 函数可以基于之前那个 promise ,dispatch 一组 type 为 pending/fulfilled/rejected 的 action

重构代码

我们对counter的reducer进行重构:通过createSlice创建一个slice切片。

// ./store/features/counter.jsimport { createSlice } from "@reduxjs/toolkit";
// 创建切片
const counterSlice = createSlice({
    name: "counter",  // 标记slice的名称
    initialState:{    // 初始化值
        counter: 888,
    },
    reducers: {   // 相当于之前的reducer函数
        addNumberAction(state,{payload}){
            state.counter += payload;
        },
        subNumberAction(state,{payload}){
            state.counter -= payload;
        }
    }
});
​
// 导出actions和reducer
export const { addNumberAction,subNumberAction } = counterSlice.actions
export default counterSlice.reducer;

createSlice主要包含下面几个参数:

  • name:用户标记slice的名称

  • initialstate: 第一次初始化的值

  • reducers:相当于之前的reducer函数

    • 对象类型,并且可以添加很多函数

    • 函数类似于原来reducer中的一个case语句;

    • 函数的参数:

      • state
      • action
  • createSlice返回值是一个对象,包含多有的actions;

store的创建

configureStore用于创建store对象,常见参数有:

  • reducer:将slice中的reducer组成一个对象传入此处;
  • middleware:可以使用参数,传入其他的中间件;
  • devTools:是否配置devTools工具,默认为true;
import { configureStore } from "@reduxjs/toolkit";
import homeReducer from "./features/home";
import counterReducer from "./features/counter";
​
const store = configureStore({
    reducer: {
        home: homeReducer,
        counter: counterReducer
    }
});
​
​
export default store;

异步操作

之前的开发中,我们通过redux-thunk中间件让dispatch中可以进行异步操作。

Redux Toolkit提供的createAsyncThunk也支持我们进行异步操作。

export const getAsyncDataAction = createAsyncThunk("fetch/data",async ()=>{
    const res = await axios.get("XXXXX");
    return res.data;
})

当createAsyncThunk创建出来的action被dispatch时,会存在三种状态:

  • pending:action被发出,但是没有最终结果;
  • fulfilled:有返回值的结果;
  • rejected:执行过程中有错误或者抛出了异常

我们可以在reducers的entraReducers中监听这些结果:

  extraReducers: {
     [fetchHomeMultidataAction.pending](state,action){
        console.log("pending");
     },
     [fetchHomeMultidataAction.fulfilled](state,action){
        console.log("fulfilled");
        console.log(action.payload);
     },
     [fetchHomeMultidataAction.rejected](state,action){
        console.log("rejected");
     }
   }

打开浏览器的控制台,发现有这个警告。让我们用builder的回调函数代替这个写法。

1679855684602.png

extraReducers的另外一种写法

extraReducers: (builder)=>{
    // 向builder中添加case来监听结果
    builder.addCase(fetchHomeMultidataAction.pending,(state,action)=>{
      console.log("pending~");
    }).addCase(fetchHomeMultidataAction.fulfilled,(state,{ payload })=>{
      console.log(payload);
    }).addCase(fetchHomeMultidataAction.rejected,()=>{
      console.log("获取数据失败了");
    })
  
}

React中的state如何管理

自此Redux中的内容我们了解的差不多了,回顾一下。

目前React中有三种状态的管理方式:

  1. 组件中自己的state
  2. contxt数据的共享状态
  3. Redux管理的状态

在开发中我们该如何选择呢?

没有标准答案。

建议:

  1. UI相关的组件内部可以维护的状态,在组件内部自己来维护。
  2. 大部分需要共享的状态,交给Redux来管理和维护;
  3. 从服务器请求的数据,交给Redux来维护

以上全部,谢谢!