Redux Toolkit:如何在当前Slice的extraReducers中分发action?
问题与解决方案
我尝试过某个方案但没用,以下是我的Slice代码:
export const getAll = () => { return axios.get('http://localhost:4000/students').then(response => { return response.data }) } export const retriveStudents = createAsyncThunk( "students/retrive", async () => { return await getAll() } ) const studentSlice = createSlice({ name: "student", initialState, reducers: { addNote: (state, action) => { return { ...state, note: action.payload } } }, extraReducers: { [retriveStudents.fulfilled]: (state, action) => { studentSlice.actions.addNote("MY DATA...") return { ...state, items: [...action.payload] } } } })
我想在extraReducers里分发addNote action,试了下面的写法但无效:
extraReducers: { [retriveStudents.fulfilled]: (state, action) => { studentSlice.actions.addNote("MY DATA...") // 此行无效 return { ...state, items: [...action.payload] } } }
问题根源
Reducer函数(包括extraReducers中的处理逻辑)是纯函数,只能负责修改state,无法直接dispatch action。你调用studentSlice.actions.addNote()只是生成了一个action对象,但没有将它分发到store,自然不会触发状态更新。
三种解决办法
办法1:直接在fulfilled回调里修改note状态(最简洁)
既然addNote的核心作用就是修改state.note,没必要单独dispatch这个action,直接在异步请求完成的回调里一起处理:
const studentSlice = createSlice({ name: "student", initialState, reducers: { addNote: (state, action) => { return { ...state, note: action.payload } } }, extraReducers: { [retriveStudents.fulfilled]: (state, action) => { // 直接合并items和note的修改,和addNote的逻辑一致 return { ...state, items: [...action.payload], note: "MY DATA..." } } } })
办法2:用监听中间件触发addNote(需保留action逻辑时用)
如果addNote还有其他关联逻辑,或者必须通过dispatch它来更新状态,可以用Redux Toolkit的createListenerMiddleware监听异步请求完成的事件,自动触发addNote:
- 创建监听中间件:
import { createListenerMiddleware } from '@reduxjs/toolkit' const listenerMiddleware = createListenerMiddleware() // 监听retriveStudents请求完成的事件 listenerMiddleware.startListening({ actionCreator: retriveStudents.fulfilled, effect: (action, listenerApi) => { // 分发addNote action listenerApi.dispatch(studentSlice.actions.addNote("MY DATA...")) } })
- 配置store时加入该中间件:
import { configureStore } from '@reduxjs/toolkit' export const store = configureStore({ reducer: { student: studentSlice.reducer }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().prepend(listenerMiddleware.middleware) })
办法3:在组件中手动连续dispatch
在调用retriveStudents的组件里,等异步请求完成后再手动dispatchaddNote:
import { useDispatch } from 'react-redux' import { retriveStudents, addNote } from './studentSlice' const MyComponent = () => { const dispatch = useDispatch() const fetchStudents = async () => { try { // 等待异步请求完成 await dispatch(retriveStudents()).unwrap() // 请求成功后分发addNote dispatch(addNote("MY DATA...")) } catch (err) { console.error('获取学生数据失败', err) } } return <button onClick={fetchStudents}>获取学生列表</button> }
内容的提问来源于stack exchange,提问作者Ghasem Khalili
相关产品推荐
相关产品推荐

