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: useAppDispatch
dispatch(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