Redux Toolkit了解及使用

451 阅读3分钟

官网

react-toolkit最大的特点是:基于切片机制,把reduceractionCreateor混在一起

官方强烈推荐的工具集,简化了redux很多文件及样板代码

安装

npm install @reduxjs/toolkit react-redux

redux-toolkit 需要借助 react-redux ,所以两个都需要安装

redux-toolkit的部分API

configureStore() 封装createStore以提供简化的配置选项和良好的默认值,默认包含redux-thunk

createSlice() 接受一个reducer函数对象、一个slice名称和一个初始状态值,并自动生成一个带有相应动作创建者和动作类型的slice reducer

开发流程

用最简单的数据加减做例子,了解redux-toolkit的使用

1.store创建

redux/react-redux使用时需要创建actions/ reducer等文件,在使用redux-toolkit是不需要创建这些

在使用redux-toolkit所需要创建的文件目录:

图片.png

features内创建不同模块的切片内容,在index.js内集成导出即可

store/index.js

import { configureStore } from '@reduxjs/toolkit'
import countSlice from './features/countSlice'

// configureStore创建一个redux数据
const store = configureStore({
    // 按模块管理各个切片导出的reducer
    reducer: {
        count: countSlice,
    },
})

export default store

这里的reducer是所有模块切片集合,统一配置

2.createSlice

使用createSlice方法创建一个slice。每一个slice里面包含了reducer和actions,可以实现模块化的封装。
所有的相关操作都独立在一个文件中完成。

切片内容:

import { createSlice } from '@reduxjs/toolkit'

export const countSlice = createSlice({
    name: 'count',
    initialState: { value: 0 },
    reducers: {
        add(state, { payload }) {
            // 进行修改数据等操作
        }
    },
})

export const { add } = countSlice.actions
export default countSlice.reducer

这个是最简单的写法

createSlice内部属性:

  • name 切片名称
  • initialState 初始值
  • reducers 内部的业务逻辑配置项

使用createSlice创建切片后,切片会自动根据配置对象生成action和reducer。action需要导出给调用处,调用处可以使用action作为dispatch的参数触发state的修改。reducer需要传递给configureStore以使其在仓库中生效。

全量代码:

import { createSlice } from '@reduxjs/toolkit'

const initialState = {
    value: 0,
}
// 模拟异步方法
const delay = (interval = 1000) => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(Math.round(Math.random() * 10))
        }, interval)
    })
}

// 创建一个Slice
export const countSlice = createSlice({
    // 设置切片名称
    name: 'count',
    // 初始状态
    initialState,
    // 编写不同业务逻辑下,对公共状态的更改
    reducers: {
        // 直接通过方法名称开发即可,不需要写switch case
        add(state, { payload }) {
            state.value += payload
        },
        sub(state) {
            state.value -= 1
        },
    },
})

// 导出加减方法
export const { add, sub } = countSlice.actions

// 实现异步派发
export const addAsync = () => {
    return async dispatch => {
        let res = await delay()
        dispatch(add(res));
    };
};

console.log("countSlice.actions", countSlice);
// 导出 reducer
export default countSlice.reducer

配置完成,在index.js内使用

3.store传递

借助了react-redux 的 Provider src/index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
// antd汉化
import { ConfigProvider } from 'antd'
import zhCN from 'antd/locale/zh_CN';

// 页面内容
import Demo from './views/rtk-test';

import store from './store';
import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <>
    <ConfigProvider locale={zhCN}>
      <Provider store={store}>
        <Demo />
      </Provider>
    </ConfigProvider>
  </>
);

4.组件使用

函数组件内,使用 useSelector 获取 store 内的数据,减少了storede 键入

使用 useDispatch 的原因,默认的dispatch对thunks不知道 所以需要 useDispatch 来进行派发,更符合RTK内的数据获取等操作

views/rtk-test.jsx

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
// 引入对应的方法
import { addAsync, sub } from '@/store/features/countSlice'
import { Button } from 'antd'

export default function Demo() {
    const count = useSelector(state => state.count.value)
    const dispatch = useDispatch()

    return (
        <div style={{ padding: '20px' }}>
            <div>展示内容:{count}</div>
            <div style={{ margin: "10px 0" }}>
                <Button type="primary" onClick={() => {
                    dispatch(addAsync())
                }} style={{ marginRight: "20px" }}>异步增加 0-10的随机数</Button>
                <Button type="primary" onClick={() => dispatch(sub())}>减少 1</Button>
            </div>
        </div>
    )
}

5.运行结果

图片.png

这里的增加是 延迟 增加数据,可以在异步这里进行接口添加、数据获取等异步操作 减少 是同步,多种用法

对比下来,RTK将reducer和actionCreator结合起来,减少了代码量