如何在extraReducers中调用另一个reducer的setLocation方法?
首先明确:Redux的Reducer是纯函数,不能在Reducer内部dispatch Action,这会破坏单向数据流原则,导致状态变化不可预测。你没法直接在extraReducers的回调里调用setLocation并触发状态更新,但可以通过以下两种合规方式实现需求:
方式一:在navigationSlice的extraReducers中直接处理loginUser.fulfilled
既然要修改navigation的location状态,最直接的方式就是在navigationSlice自己的extraReducers里监听loginUser.fulfilled动作,直接更新location值,完全不需要依赖其他slice或dispatch:
import { createSlice } from '@reduxjs/toolkit'; import { getCurrentPageLocation } from '../../utils'; // 导入loginUser这个异步thunk import { loginUser } from '../path-to-auth-slice'; const initialState = { location: getCurrentPageLocation() }; const navigationSlice = createSlice({ name: 'navigation', initialState, reducers: { setLocation: (state, action) => { state.location = action.payload; } }, extraReducers: (builder) => { builder.addCase(loginUser.fulfilled, (state) => { // 直接修改当前slice的location状态,比如设为HomePage的路径 state.location = '/home'; }); } }); export const { setLocation } = navigationSlice.actions; export default navigationSlice.reducer;
这种方式完全符合Redux的设计原则,每个slice只负责自己的状态更新逻辑,代码清晰且可维护。
方式二:如果必须在原slice的extraReducers中触发状态更新(不推荐)
如果业务逻辑确实需要在原slice(比如authSlice)的loginUser.fulfilled回调中触发navigation的状态变化,只能通过在createAsyncThunk中使用thunkAPI.dispatch实现——这是Redux中跨slice触发action的标准途径:
// 在定义loginUser的异步thunk文件中 import { createAsyncThunk } from '@reduxjs/toolkit'; import { setLocation } from '../path-to-navigation-slice'; export const loginUser = createAsyncThunk( 'auth/loginUser', async (credentials, { dispatch }) => { // 执行登录逻辑 const user = await api.login(credentials); // 登录成功后dispatch setLocation dispatch(setLocation('/home')); return user; } );
原slice的extraReducers只需处理auth相关状态:
builder .addCase(loginUser.pending, (state) => { state.isLoading = true; }) .addCase(loginUser.fulfilled, (state, action) => { state.isLoading = false; state.user = action.payload; toast.success('Logged In User!'); }) .addCase(loginUser.rejected, (state, action) => { state.isLoading = false; toast.error(action.payload); });
补充说明
setLocation是一个action creator,调用它只会生成一个action对象,但Reducer本身没有dispatch能力——Redux的状态更新流程是:dispatch action → 所有reducer处理action → 更新状态。Reducer只是纯函数,负责计算新状态,不能发起新的action。
内容的提问来源于stack exchange,提问作者Bop 1ABot

