Redux Toolkit 是官方推荐的编写 Redux 逻辑的方法。
在前面我们学习Redux的时候应该已经发现,redux的编写逻辑过于的繁琐和麻烦。
并且代码通常分拆在多个文件中(虽然也可以放到一个文件管理,但是代码量过多,不利于管理);
Redux Toolkit包旨在成为编写Redux逻辑的标准方式,从而解决上面提到的问题;
在很多地方为了称呼方便,也将之称为“RTK”;
安装Redux Toolkit
npm install @reduxjs/toolkit react-redux
Redux Toolkit的核心API主要是如下几个:
configureStore:包装createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供
的任何 Redux 中间件,redux-thunk默认包含,并启用 Redux DevTools Extension。
createSlice:接受reducer函数的对象、切片名称和初始状态值,并自动生成切片reducer,并带有相应的actions。
createAsyncThunk: 接受一个动作类型字符串和一个返回承诺的函数,并生成一个pending/fulfilled/rejected基于该承诺分
派动作类型的 thunk
我们先对counter的reducer进行重构: 通过createSlice创建一个slice。
createSlice主要包含如下几个参数:
name:用户标记slice的名词
在之后的redux-devtool中会显示对应的名词;
initialState:初始化值
第一次初始化时的值;
reducers:相当于之前的reducer函数
对象类型,并且可以添加很多的函数;
函数类似于redux原来reducer中的一个case语句;
函数的参数:
参数一:state
参数二:调用这个action时,传递的action参数;
createSlice返回值是一个对象,包含所有的actions;
import { createSlice } from "@reduxjs/toolkit"
const counterSlice = createSlice({
name: "counter",
initialState: {
counter: 888
},
reducers: {
addNumber(state, { payload }) {
state.counter = state.counter + payload
},
subNumber(state, { payload }) {
state.counter = state.counter - payload
}
}
})
export const { addNumber, subNumber } = counterSlice.actions
export default counterSlice.reducer
configureStore用于创建store对象,常见参数如下:
reducer,将slice中的reducer可以组成一个对象传入此处;
middleware:可以使用参数,传入其他的中间件;
devTools:是否配置devTools工具,默认为true;
import { configureStore } from "@reduxjs/toolkit"
import counterReducer from "./features/counter"
import homeReducer from "./features/home"
const store = configureStore({
reducer: {
counter: counterReducer,
home: homeReducer
}
})
export default store
在之前的开发中,我们通过redux-thunk中间件让dispatch中可以进行异步操作。
Redux Toolkit默认已经给我们继承了Thunk相关的功能:createAsyncThunk
export const getHomeMultidataAction = createAsyncThunk('a/b', async (extraInfo, { dispatch, getState }) => {
const res = await axios.get('http://..../a/b')
return res.data.data
})
当createAsyncThunk创建出来的action被dispatch时,会存在三种状态
pending: action被发出,但是还没有最终的结果。
fulfilled: 获取到最终的结果(如果由返回值的结果)
rejected: 执行过程中由错误或者抛出了异常
我们可以在createSlice的entraReducder中监视这些结果
extraReducers: {
[getHomeMultidataAction.pending](state, action) {
console.log("getHomeMultidataAction pending", action)
},
[getHomeMultidataAction.fulfilled](state, {payload}) {
console.log("getHomeMultidataAction fuilfilled", payload)
state.banners = payload.banner.list
state.recommends = payload.recommend.list
},
[getHomeMultidataAction.rejected](state, action){
console.log("getHomeMultidataAction rejected", action)
}
}
extraReducer的另外一种写法
extraReducer还可以传入一个函数,函数接受一个builder参数。
我们可以向builder中添加case来监听异步操作的结果:
extraReducers: (builder) => {
builder.addCase(getHomeMultidataAction.pending, (state) => {
console.log("getHomeMultidataAction pending")
}).addCase(getHomeMultidataAction.fulfilled, (state,{payload}) => {
state.banners = payload.banner.list
state.recommends = payload.recommend.list
})
}