Redux Toolkit+TypeScript最佳实践

Redux-Toolkit是为了简化使用Redux繁琐的步骤,可以j降低使用useReducer与useContext管理状态的频率,而且起到项目中状态管理规范和约束化的效果。

阅读本文需要的前置知识:React、Redux、Typescript、Redux hooks。

Redux-Toolkit使用步骤

目前使用Redux-Toolkit管理消费redux状态的方式。举个例子,假设我们现在的业务和银行转账有关,有两个状态存在redux,分别为银行账号和金额:accountOfBank和amountOfBank,使用createSlice来创建reducer和actions:

首先安装redux-toolkit依赖包,

npm i @reduxjs/toolkit

npm i react-redux

文件目录

slice.ts

创建切片,声明存储状态对象以及action。createSlice创建一个切片(slice),主要参数:

  • name:slice的标识,在redux-devtool中会显示对应的名字;
  • initialState:初始值,对象;
  • reducers:对象类型以及函数类型(函数参数:state和传递的action参数);
  • extraReducers:用于处理异步,比如网络请求等;

creactSlice返回值是一个对象,包含所有的actions。 

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

type InitialState = {
    accountOfBank: string,
    amountOfBank: string
}


const initialState: InitialState = {
    accountOfBank: 'JanPan Bank',
    amountOfBank: '1000'
}

const slice = createSlice({
    name: 'bank',
    initialState,
    reducers: {
        updateBankAccount: (state: InitialState, action: PayloadAction<string>) => {
            state.accountOfBank = action.payload;
        },
        updateBankAmount: (state: InitialState, action: PayloadAction<string>) => {
            state.amountOfBank = action.payload;
        }
    }
})

export const {updateBankAccount, updateBankAmount} = slice.actions;
export default slice.reducer;

 store.ts

存在在store中,configureStore是Redux-Tookit的一个工厂函数,用于创建Redux-Store。

store是通过传入一个reducer(缩减器)来创建的,并通过getState的方法,用于返回当前的状态值,在Typescript强类型声明中有很大的帮助。

configureStore主要参数,

  • reducer:将slice的reducer传入;
  • middleware:中间件;
  • devTools:是否配置devTools工具,默认为true;
import { configureStore } from "@reduxjs/toolkit";
import slice from './slice';

export const store = configureStore({
    reducer: {
        bank: slice
    }
})

export type BankState = ReturnType<typeof store.getState>;

index.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from "react-redux";
import { store } from "./toolkit/store";
const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
    <Provider store={store}>
        <App />
    </Provider>
);

BankView.tsx

页面UI组件渲染,useSelector获取当前管理的state,state的类型可通过store.ts的getState获取,

并且将配置在store的reducer提取解构。

import { useDispatch, useSelector } from "react-redux";
import { BankState } from "../../toolkit/store";
import { updateBankAccount, updateBankAmount } from "../../toolkit/slice";

export const BankView = () => {
    const {accountOfBank, amountOfBank} = useSelector((state: BankState) => state.bank)

    const dispatch = useDispatch();

    return (
        <div>
            <h3>accountOfBank - {accountOfBank}</h3>
            <h3>amountBank - {amountOfBank}</h3>
            <button onClick={() => dispatch(updateBankAccount('England'))}>
                change bank account
            </button>
            <span>  </span>
            <button onClick={() => dispatch(updateBankAmount('2000'))}>
                change bank amount
            </button>
        </div>
    )
}

详细目录截图如下,

经过上面简单的封装就实现了全局状态管理,使用简单高效,而且可以实现业务与UI的解耦。

在网络请求等情况通常需要异常更新、提交数据等,可通过createAynceThunk实现,

import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';

type InitialState = {
    accountOfBank: string,
    amountOfBank: string,
    creatTime: string
}


const initialState: InitialState = {
    accountOfBank: 'JanPan Bank',
    amountOfBank: '1000',
    creatTime: '2024-04-02'
}


export const fetchAccountBank = createAsyncThunk(
    'https://wwww.baidu.com',
    () => {
        return new Promise<string>(resolve => {
            let timeId = setTimeout(() => {
                clearTimeout(timeId);
                resolve('2024-04-03');
            }, 1000)
        })
    })

const slice = createSlice({
    name: 'bank',
    initialState,
    reducers: {
        updateBankAccount: (state: InitialState, action: PayloadAction<string>) => {
            state.accountOfBank = action.payload;
        },
        updateBankAmount: (state: InitialState, action: PayloadAction<string>) => {
            state.amountOfBank = action.payload;
        }
    },
    extraReducers: (builder) => {
        builder.addCase(fetchAccountBank.pending, (state: InitialState) => {
            console.log('fetchAccountBank pending')
            state.creatTime = 'loading...'
        });
        builder.addCase(fetchAccountBank.fulfilled, (state, action) => {
            console.log(action.payload)
            state.creatTime = action.payload;
            console.log('fetchAccountBank fulfilled')
        });
        builder.addCase(fetchAccountBank.rejected, (state) => {
            console.log('fetchAccountBank rejected')
            state.creatTime = 'failed...'
        })
    }
})

export const {updateBankAccount, updateBankAmount,} = slice.actions;
export default slice.reducer;

因为Typescript语言有较强的类型校验,在异步时dispatch报错,如下

只需在使用useDispatch时,声明泛型类型即可。

    // 异步需声明useDispatch类型
    const asyncDispatch = useDispatch<AppDispatch>();

最佳实践全部代码如下:

ReduxToolkit+TypeScript最佳实践资源-CSDN文库

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上的追梦人

您的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值