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

 

posted @ 2021-12-01 17:44  天官赐福·  阅读(888)  评论(0编辑  收藏  举报
返回顶端