Redux Toolkit的使用
1.使用推荐命令创建项目:
npx create-react-app AppName --template redux
2.分析项目代码:
2.1 store.js
import { configureStore } from '@reduxjs/toolkit';//可以融合多个reducer,并集成了redux-thunk,Redux DevTools import counterReducer from '../features/counter/counterSlice'; export const store = configureStore({ reducer: { counter: counterReducer, }, });
对比旧版本代码:
import { createStore, applyMiddleWar, combineReducers} from 'redux'; import thunk from 'redux-thunk'; const reducers = combineReducers({counter:counterReducer}); const store = createStore(reducers,{}, applyMiddleWar, thunk));
2.2 counterSlice文件:
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; import { fetchCount } from './counterAPI'; // 初始化的数据 const initialState = { value: 0, status: 'idle', }; // 异步请求的方法 export const incrementAsync = createAsyncThunk( 'counter/fetchCount',//请求的接口地址 async (amount) => { //amount 为请求的参数 const response = await fetchCount(amount);//接收请求的响应数据 // 这个返回值,将会在 fulfilled 成功状态的 action.payload 中获取 return response.data; } ); // 创建slice(片段)-- 集成了createReducer,createAction(@reduxjs/toolkit中的方法) export const counterSlice = createSlice({ name: 'counter', //slice的名字 initialState, //初始化数据 // 定义reducers reducers: { increment: (state) => { // 集成了Immer库,它检测到“draft state"”的更改并生成一个全新的 state.value += 1; }, decrement: (state, action) => { state.value -= 1; }, //调用方法传入的参数都在action.payload属性中 incrementByAmount: (state, action) => { state.value += action.payload; }, }, // 额外的reducer,用来处理异步请求方法 extraReducers: (builder) => { builder .addCase(incrementAsync.pending, (state) => {//pending请求过程中 state.status = 'loading';//设置loading }) .addCase(incrementAsync.fulfilled, (state, action) => {//fulfilled请求完成 state.status = 'idle';//取消loading state.value += action.payload;//将请求的响应数据设置到slice中 //action.payload就是上面incrementAsync方法return出来的响应数据 }) .addCase(incrementAsync.rejected, (state, action) => { //rejected请求拒绝 }); }, }); // 将action方法暴露出去 export const { increment, decrement, incrementByAmount } = counterSlice.actions; // 可以选择一个值暴露出去,使用方法:import {selectCount} from './counterSlice'; const counter = useSelector(selectCount); // 也可以在文件中直接采用:const counter = useSelector((state: RootState) => state.counter.value) export const selectCount = (state) => state.counter.value; //我们也可以手工编写thunk,它可能包含同步和异步逻辑。 //下面是一个基于当前状态有条件地分派操作的示例。 export const incrementIfOdd = (amount) => (dispatch, getState) => { // amount是调用方法传入的参数 // getState()方法可以获取到项目中store中所有的reducer数据 // selectCount(getState()) 获取到的是当前slice中的value数据 const currentValue = selectCount(getState()); if (currentValue % 2 === 1) { // 当前值如果为基数的话执行下面的函数 这里调用了slice中的其他方法 dispatch(incrementByAmount(amount)); } }; // 把当前创建的reducer暴露出去(必不可少) export default counterSlice.reducer;
3.看看slice中的方法和数据都是怎么使用的:
import { useSelector, useDispatch } from 'react-redux'; import { decrement, increment, incrementByAmount, incrementAsync, incrementIfOdd, selectCount, } from './counterSlice'; const count = useSelector(selectCount);//获取到的是slice中的value数据 // 等同于 === 》 const counter = useSelector((state) => state.counter.value)
//const { value, status } = useSelector(state => state.counter) 可以一次解构多个数据 const dispatch = useDispatch(); <button onClick={() => dispatch(decrement())}> - <button>//调用方法
<button onClick={() => dispatch(incrementByAmount(incrementValue))}> Add Amount <button>
<button onClick={() => dispatch(incrementIfOdd(incrementValue))}> Add If Odd <button>
4.处理thunk的返回结果:
4.1直接在请求方法中进行
export const fetchCustomer = createAsyncThunk( `${namespaces}/fetchCustomer`, async (params: ParamsTypes, { dispatch }) => { const { changeLoading } = customerSlice.actions; dispatch(changeLoading(true)); const res = await server.fetchCustomer(params); dispatch(changeLoading(false)); if (res.status === 0) { return res.data; } else { message.error(res.message); } }, );
4.2 使用try...catch
const updateUser = createAsyncThunk( 'users/update', async (userData, { rejectWithValue }) => { const { id, ...fields } = userData try { const response = await userAPI.updateById(id, fields) return response.data.user } catch (err) { // Use `err.response.data` as `action.payload` for a `rejected` action, // by explicitly returning it using the `rejectWithValue()` utility return rejectWithValue(err.response.data) } } )
官方中文文档:http://cn.redux.js.org/redux-toolkit/overview
参考地址:
https://blog.csdn.net/ilovethesunshine/article/details/109627560
https://blog.csdn.net/dfsgwe1231/article/details/107258846
https://www.jianshu.com/p/3f4e6fef4d89
https://blog.csdn.net/pig_fu/article/details/113870074