一、基本使用

  • 1、官网地址

  • 2、在项目中直接安装

    npm install @reduxjs/toolkit react-redux
    
  • 3、查看@reduxjs/toolkit的依赖包

    其中自动集成了thunk处理异步的包

    ...
    "dependencies": {
        "immer": "^9.0.1",
        "redux": "^4.0.0",
        "redux-thunk": "^2.3.0",
        "reselect": "^4.0.0"
      },
    ...
    
  • 4、在store文件夹下创建一个activity/slice.ts文件

    import { createSlice, PayloadAction} from '@reduxjs/toolkit';
    
    export interface ActivityState {
      data: any;
      total: number;
      pageNumber: number;
      pageSize: number;
      loading: boolean; // 请求数据中
      error: string | null; // 是否错误
    }
    
    const initialState: ActivityState = {
      data: [],
      total: 0,
      pageNumber: 1,
      pageSize: 10,
      loading: true,
      error: null,
    }
    
    export const activityListSlice = createSlice({
      name: 'activity', 
      initialState,
      reducers: {
        fetchStart: (state) => {
          // return { ...state, loading: true };
          state.loading = true;
        },
        fetchSuccess: (state, action) =>{
          // return {
          //   ...state,
          //   loading: false,
          //   data: action.payload.data,
          //   total: action.payload.total,
          //   pageNumber: action.payload.pageNumber,
          //   pageSize: action.payload.pageNumber,
          // };
          state.loading = false;
          state.data = action.payload.data;
          state.total = action.payload.total;
          state.pageNumber = action.payload.pageNumber;
          state.pageSize = action.payload.pageSize;
        },
        fetchFail: (state, action: PayloadAction<string | null>) => {
          state.loading = false;
          state.error = action.payload;
        }
      }
    })
    
  • 5、在store的入口文件中合并reducer

    mport { combineReducers, configureStore } from '@reduxjs/toolkit';
    import { activityListSlice } from './activity/slice';
    
    // 合并多个reducer
    const rootReducer = combineReducers({
      ...
      activity: activityListSlice.reducer,
    })
    const store = configureStore({
      reducer: rootReducer,
      // 可以添加自己的中间件,比如打印日志的
      middleware: (getDefaultMiddleware) => [...getDefaultMiddleware()],
      devTools: true,
    });
    
    // 获取全部store数据类型
    export type RootState = ReturnType<typeof store.getState>;
    
    export default store;
    
  • 6、在页面组件中直接调用远程api接口

    import React, { PropsWithChildren, useEffect } from 'react';
    import { RouteComponentProps } from 'react-router-dom';
    import {useDispatch} from 'react-redux';
    import { useSelector } from '../../redux/hooks';
    import { activityListSlice } from '../../redux/activity/slice';
    import axios from 'axios';
    
    interface MatchParams {
      id: string;
    }
    
    type Props = PropsWithChildren<RouteComponentProps<MatchParams>>;
    
    export const Detail: React.FC<Props> = (props: Props) => {
      console.log(props);
      const loading = useSelector(state =>state.activity.loading);
      const activityList = useSelector(state => state.activity.data);
      const dispatch = useDispatch();
    	// 页面一进来就加载数据
      useEffect(() => {
        const fetchData = async () => {
          dispatch(activityListSlice.actions.fetchStart());
          try {
            const { data } = await axios.get('https://xxxx/api/v1/front/activity');
            const {code, message, result} = data;
            if (Object.is(code, 0)) {
              dispatch(activityListSlice.actions.fetchSuccess(result));
            } else {
              dispatch(activityListSlice.actions.fetchFail(message));
            }
          } catch(e) {
            dispatch(activityListSlice.actions.fetchFail(e.messages));
          }
        }
        fetchData();
      }, []);
      if (loading) {
        return <h1>数据加载中</h1>
      }
      return (
        <div>
          {
            activityList.map(item => {
              return <li key={item.id}>{item.title}</li>
            })
          }
        </div>
      )
    }
    

二、将请求后端接口也放到redux中去

  • 1、定义请求方法

    import { createSlice, PayloadAction, createAsyncThunk} from '@reduxjs/toolkit';
    import axios from 'axios';
    
    export const getActivityList = createAsyncThunk(
      'activity/getActivityList', // 唯一的
      async (params:any, thunkAPI) => {
        console.log(params, '接口需要的参数');
        thunkAPI.dispatch(activityListSlice.actions.fetchStart());
        try {
          const { data } = await axios.get('https://test.dancebox.cn/api/v1/front/activity');
          const { code, message, result } = data;
          if (Object.is(code, 0)) {
            thunkAPI.dispatch(activityListSlice.actions.fetchSuccess(result));
          } else {
            thunkAPI.dispatch(activityListSlice.actions.fetchFail(message));
          }
        } catch (e) {
          thunkAPI.dispatch(activityListSlice.actions.fetchFail(e.messages));
        }
      }
    );
    
  • 2、在页面中调用方法

    useEffect(() => {
        dispatch(getActivityList({name: '哈哈', age:20}));
    }, []);
    

三、另外一种官方推荐的请求接口的方式

  • 1、在redux中定义

    export const getActivityList = createAsyncThunk(
      'activity/getActivityList',
      async (params:any) => {
        console.log(params, '接口需要的参数');
        const { data } = await axios.get('https://test.dancebox.cn/api/v1/front/activity');
        return data;
      }
    );
    
    export const activityListSlice = createSlice({
      name: 'activity', 
      initialState,
      reducers: {
        
      },
      // 注意这个位置是在extraReducers中
      extraReducers: {
        [getActivityList.pending.type]: (state) => {
          state.loading = true;
        },
        [getActivityList.fulfilled.type]: (state, action) => {
          const { code, message, result: {data, total, pageSize, pageNumber} } = action.payload;
          if (Object.is(code, 0)) {
            state.loading = false;
            state.data = data;
            state.total = total;
            state.pageNumber = pageNumber;
            state.pageSize = pageSize;
          } else {
            state.loading = false;
            state.error = message;
          }
        },
        [getActivityList.rejected.type]: (state, action: PayloadAction<string | null>) => {
          state.loading = false;
          state.error = action.payload;
        }
      }
    })
    
  • 2、在页面中调用

    useEffect(() => {
        dispatch(getActivityList({name: '哈哈', age:20}));
    }, []);