项目目前用的React版本是 17.0.2

react-redux负责状态管理,使用toolkit插件可以更加方便。

toolkit官网

1. 安装redux

1
2
npm install react-redux@latest
npm install @reduxjs/toolkit

2. 使用tookit

  1. 配置一个reduxStore

    1
    2
    3
    4
    import { configureStore } from '@reduxjs/toolkit';
    export const store = configureStore({
    reducer: {},
    });
  2. 把store发布到react项目中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import { Provider } from 'react-redux';
    import { store } from './app/store';
    import App from './App';

    ReactDOM.render(
    <Provider store={store}>
    <App />
    </Provider>,
    document.getElementById('root')
    );
  3. 创建不定量的redux state slice,创建不同的slice.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import { createSlice } from '@reduxjs/toolkit';

    const initialState = {
    value: 0,
    };

    export const counterSlice = createSlice({
    name: 'counter',
    initialState,
    reducers: {
    increment: (state) => {
    state.value += 1;
    },
    decrement: (state) => {
    state.value -= 1;
    },
    incrementByAmount: (state, action) => {
    state.value += action.payload;
    },
    },
    });
    export const { increment, decrement, incrementByAmount } = counterSlice.actions
    export default counterSlice.reducer
  4. 把slice reducers添加到store中

    1
    2
    3
    4
    5
    6
    7
    import { configureStore } from '@reduxjs/toolkit';
    import counterReducer from './counter/counterSlice'
    export const store = configureStore({
    reducer: {
    counter: counterReducer,
    },
    });
  5. 在组件中使用state和actions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    import React from 'react';
    import {useSelector, useDispatch} from 'react-redux';
    import {increment, decrement} from './counterSlice';

    export function Counter() {
    //从store中选择所需要的对应的 state
    const count = useSelector((state) => state.counter.value);
    const dispatch = useDispatch();

    return (
    <div>
    <div>
    <button
    aria-label="Increment value"
    onClick={() => dispatch(increment())}
    >
    Increment
    </button>
    <span>{count}</span>
    <button
    aria-label="Decrement value"
    onClick={() => dispatch(decrement())}
    >
    Decrement
    </button>
    </div>
    </div>
    );
    }

3. 总结

  • 使用toolkit配置一个空状态管理仓库:store
  • 将刚配置的空的状态管理仓库配合react-redux中的Provider使用到项目中,一般需要将 Provider包裹在项目的最顶层父级元素外,这样可以保证这个store能够存储项目内的所有state
  • 使用toolkit中createSlice创建每个state对应的actions(一般一个状态的reducer放置在一个单独的文件中,便于管理和查看)
  • 把第3步创建好的不定量个数的reducer配置到第1步创建的store中
  • 在项目中使用react-redux中提供的useSelectoruseDispatch分别负责从store中获取对应的state以及触发改变state的动作函数reducer
  • 注意:若state的动作函数是一个异步请求,则第3步中需要使用createAsyncThunk来创建state对应的action:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
    import { userAPI } from './userAPI'

    // First, create the thunk
    const fetchUserById = createAsyncThunk(
    'users/fetchByIdStatus',
    async (userId, thunkAPI) => {
    const response = await userAPI.fetchById(userId)
    return response.data
    }
    )

    // Then, handle actions in your reducers:
    const usersSlice = createSlice({
    name: 'users',
    initialState: { entities: [], loading: 'idle' },
    reducers: {
    // standard reducer logic, with auto-generated action types per reducer
    },
    extraReducers: (builder) => {
    // Add reducers for additional action types here, and handle loading state as needed
    builder.addCase(fetchUserById.fulfilled, (state, action) => {
    // Add user to the state array
    state.entities.push(action.payload)
    })
    },
    })

    // Later, dispatch the thunk as needed in the app
    dispatch(fetchUserById(123))