redux Toolkit(TypeScript版本)之基本使用


基础使用: redux Toolkit的使用

redux Toolkit之TypeScript使用

官文档中文地址:Redux Toolkit TypeScript 快速开始

store.ts
import {
  configureStore,
  combineReducers,
  ThunkAction,
  Action
} from '@reduxjs/toolkit'
import {
  persistStore,
  persistReducer
} from 'redux-persist'
import storage from 'redux-persist/lib/storage'

import testSlice from './slice/testSlice'
import themeSlice from './slice/themeSlice'
import userSlice from './slice/userSlice'
import utilsSlice from './slice/utilsSlice'

export const rootReducer = combineReducers({
  user: userSlice,
  theme: themeSlice,
  utils: utilsSlice,
  test: testSlice
})

// 持久化
const persistConfig = {
  key: 'wgh',
  storage,
  blacklist: ['utils', 'test'],	// 黑名单:不持久化的slice
}
const myPersistReducer = persistReducer(persistConfig, rootReducer)
export const store = configureStore({
  // reducer: {
  //   user: userSlice,
  //   theme: themeSlice
  // }
  reducer: myPersistReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware({
    serializableCheck: false
  })
})

export const persistor = persistStore(store)

// 类型
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch

export type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  RootState,
  unknown,
  Action<string>
>;
自定义hooks

组件使用时将原来的 useDispatch, useSelector 换成useAppDispatchuseAppSelector 即可

import { useDispatch, useSelector } from 'react-redux'
import type { TypedUseSelectorHook } from 'react-redux'
import type { RootState, AppDispatch } from './store'

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

// import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
// import type { RootState, AppDispatch } from './store';

// // Use throughout your app instead of plain `useDispatch` and `useSelector`
// export const useAppDispatch = () => useDispatch<AppDispatch>();
// export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
testSlice.ts
import { RootState, AppThunk } from '../store';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'

export interface TestState {
  value: number
  num: number
  status: 'idle' | 'loading' | 'failed'
}

const initialState: TestState = {
  value: 0,
  num: 10,
  status: 'idle',
}

// 模拟后端请求(异步)
export function fetchCount(amount = 1) {
  return new Promise<{ data: number }>((resolve) =>
    setTimeout(() => resolve({ data: amount }), 500)
  );
}

// 异步:第一个参数相当于 type: "test/fetchCount"
export const incrementAsync = createAsyncThunk(
  "test/fetchCount",
  async (amount: number) => {
    const res = await fetchCount(amount)
    // 返回的值成为 "fulfilled "动作的有效载荷
    return res.data
  }
);


export const testSlice = createSlice({
  name: 'test',
  initialState,
  reducers: {
    increment: (state) => {
      state.value ++
    },
    incrementByAmount: (state, action: PayloadAction<number>) => {
      state.value += action.payload;
    },
  },
  // 额外的reducers,包括但不限于createAsyncThunk产生的动作
  extraReducers(builder) {
    builder
      .addCase(incrementAsync.pending, (state) => {
        // incrementAsync执行准备阶段
        state.status = 'loading'
      })
      .addCase(incrementAsync.fulfilled, (state, action) => {
        // incrementAsync执行成功阶段
        state.status = 'idle'
        // 成功后执行的操作
        // action.payload 是incrementAsync返回数据
        state.value += action.payload
        state.num+= action.payload
      })
      .addCase(incrementAsync.rejected, (state, action) => {
        // incrementAsync执行失败阶段
        state.status = 'failed'
        console.log('error', action.error.message)
        // state.error = action.error.message
      })
  }
})

// Action creators are generated for each case reducer function
export const { increment, incrementByAmount } = testSlice.actions

export default testSlice.reducer

// 函数选择器,内联定义
export const selectCount = (state: RootState) => state.test.value;

// 手工编写thunks:可以包含同步、异步逻辑或根据当前状态执行
export const incrementIfOdd =
  (amount: number): AppThunk =>
    (dispatch, getState) => {
      // amount:组件传递的参数 currentValue:当前 num 值
      const currentValue = selectCount(getState());
      // 执行条件
      if (currentValue % 2 === 1) {
        dispatch(incrementByAmount(amount));
      }
    };


组件中使用
import { Button, Space } from 'antd'
import { useAppDispatch, useAppSelector } from '@/redux/hooks'
import { incrementIfOdd, increment, selectCount, incrementAsync, TestState  } from '@/redux/slice/testSlice'

const Test= () => {
  const test: TestState = useAppSelector(state => state.test)
  const count = useAppSelector(selectCount)
  const dispatch = useAppDispatch()

  return (
    <div style={{
      display: 'flex',
      flexDirection: 'column'
    }}>
      <Space>
        <div>value: {count}</div>
        <div>num: {test.num}</div>
        <Button onClick={() => dispatch(increment())}>同步</Button>
        <Button type="primary" onClick={() => dispatch(incrementAsync(5))}>异步</Button>
        <Button danger onClick={() => dispatch(incrementIfOdd(count))}>条件</Button>
      </Space>
    </div>
  )
}

export default Test
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

凡小多

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值