react+redux异步操作数据

react+redux异步操作数据

redux中操作异步方法,主要是: 1、借助createAsyncThunk()封装异步方法;2、通过extraReducers处理异步方法触发后的具体逻辑,操作派生的state

1、异步操作的slice

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

// 使用该类型定义初始 state
const initialState = {
  systemName: '三分之一'
}
// promise封装的定时器
function delay(ms: number, data: string) {
  return new Promise((resolve) => setTimeout(() => resolve(data), ms))
}
// AsyncThunk
// createAsyncThunk :
// 第一个string: 'system/updateSystemName'
// 第二个string: updateSystemName调用时,传的参数
// object: AsyncThunkConfig 配置对象
// 详细可见 : https://redux-toolkit.js.org/usage/usage-with-typescript#createasyncthunk
export const updateSystemName = createAsyncThunk<string, string>(
  'system/updateSystemName',
  async (data, config): Promise<string> => {
    console.log(data, config)
    const res = await delay(2000, data)
    return res as string
  }
)

const systemSlice = createSlice({
  name: 'system',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    // 触发updateSystemName,执行builder.addCase的回调
    builder.addCase(updateSystemName.fulfilled, (state, action) => {
      // action: {
      //   type: 'system/updateSystemName/fulfilled'
      // },
      // payload: dispatch(updateSystemName('单点的')) updateSystemName
      // meat: {arg: '单点的', ...}
      state.systemName = action.payload
    })
  }
})
export default systemSlice.reducer

AsyncThunkConfig 如图所示:
react+redux异步操作数据_第1张图片

2、组件中调用异步的方法

import { updateSystemName } from '@/store/reducers/systemSlice'
import { RootState } from '@/store'
import { useAppDispatch } from '@/hooks/useAppDispatch'
import { useAppSelector } from '@/hooks/useAppSelector'

const Home = () => {
  const { systemName } = useAppSelector(
    (state: RootState) => state.systemReducer
  )
  const dispatch = useAppDispatch()
  const test = () => {
    // useDispatch() 返回值函数默认期望的参数类型是 AnyAction
    // 异步处理是updateSystemName: AsyncThunkAction
    // 所以这块使用官网推荐的自定义封装的hooks: useAppDispatch
    dispatch(updateSystemName('单点的'))
  }
  return (
    <>
      <div>home page</div>
      <p>{systemName}</p>
      <button onClick={test}>测试</button>
    </>
  )
}

export default Home

4、给dispatch()参数添加Action类型

解决: 类型“AsyncThunkAction”的参数不能赋给类型“AnyAction”的参数。

  1. useAppDispatch
import type { AppDispatch } from '@/store'
import { useDispatch } from 'react-redux'

// 给useDispatch 添加泛型, 默认接收的参数是AnyAction
// import {  useDispatch } from 'react-redux'
export const useAppDispatch = () => useDispatch<AppDispatch>()
  1. useAppSelector
import type { RootState } from '@/store'
import { TypedUseSelectorHook, useSelector } from 'react-redux'

// import { useSelector } from 'react-redux'
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
  1. store中
    export type RootState = ReturnType
    export type AppDispatch = typeof store.dispatch
import { configureStore } from '@reduxjs/toolkit'
import { combineReducers } from 'redux'
// 数据持久化
import { persistStore, persistReducer } from 'redux-persist'
import storageLocation from 'redux-persist/lib/storage' // defaults to localStorage for web    // redux-persist/lib/storage/session
// reducers
import userReducer from './reducers/userSlice'
import systemReducer from './reducers/systemSlice'
const persistConfig = {
  key: 'root',
  storage: storageLocation
}
// 持久化reducers
const persistedReducer = persistReducer(
  persistConfig,
  combineReducers({
    //数据切片
    userReducer,
    systemReducer
  })
)

const store = configureStore({
  // userReducer 模块名
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: false
    })
})

// 可以订阅 store
// store.subscribe(() => console.log(store.getState(), 'userSlice'))

// 持久化的store
const persistor = persistStore(store)

export { store, persistor }

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch

你可能感兴趣的:(react.js,前端,前端框架)