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<void, void, AsyncThunkConfig>
// createAsyncThunk<string, string, object> :
// 第一个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 如图所示:
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: useAppDispatchdispatch(updateSystemName('单点的'))}return (<><div>home page</div><p>{systemName}</p><button onClick={test}>测试</button></>)
}export default Home
4、给dispatch()参数添加Action类型
解决: 类型“AsyncThunkAction<string, string, AsyncThunkConfig>”的参数不能赋给类型“AnyAction”的参数。
useAppDispatch
import type { AppDispatch } from '@/store'
import { useDispatch } from 'react-redux'// 给useDispatch 添加泛型, 默认接收的参数是AnyAction
// import { useDispatch } from 'react-redux'
export const useAppDispatch = () => useDispatch<AppDispatch>()
useAppSelector
import type { RootState } from '@/store'
import { TypedUseSelectorHook, useSelector } from 'react-redux'// import { useSelector } from 'react-redux'
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
- store中
export type RootState = ReturnType<typeof store.getState>
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