如何用Redux Toolkit的createSlice实现多Reducer响应同一Action
Hey there! Great question—you absolutely can get multiple slice reducers to react to a single action dispatch using Redux Toolkit, just like you could with vanilla Redux. The key here is understanding that each slice's auto-generated action creators have unique type strings (prefixed with the slice name), which is why your original code only updated one state at a time. Let's fix that with a couple of straightforward approaches.
Approach 1: Use extraReducers to Listen to Another Slice's Action
Redux Toolkit's createSlice includes an extraReducers option specifically for handling actions that aren't defined in the slice's own reducers field. You can use this to have your currentUser slice listen to the loginSuccess and logout actions exported from the isAuthenticated slice.
Here's the modified code:
import { createSlice } from '@reduxjs/toolkit'; // First slice: handles authentication state const isAuthenticated = createSlice({ name: 'isAuthenticated', initialState: false, reducers: { loginSuccess(state, action) { return true; }, logout(state, action) { return false; }, }, }); export const { loginSuccess, logout } = isAuthenticated.actions; export default isAuthenticated.reducer; // Second slice: handles current user, now listening to the same actions const currentUser = createSlice({ name: 'currentUser', // Fixed the typo from "currenUser" initialState: 'john', // Fixed the typo from "jhon" reducers: { // Keep any user-specific reducers here if needed }, extraReducers: (builder) => { // Listen to the loginSuccess action from isAuthenticated slice builder.addCase(loginSuccess, (state, action) => { return 'steve'; }); // Listen to the logout action from isAuthenticated slice builder.addCase(logout, (state, action) => { return state; // Or update to empty string/null if needed }); }, }); export const currentUserReducer = currentUser.reducer;
Now when you dispatch loginSuccess() anywhere in your app, both reducers will run: the isAuthenticated slice sets the state to true, and the currentUser slice updates to 'steve'—all with a single dispatch.
Approach 2: Define Shared Action Creators Separately
If you prefer to keep your shared actions centralized (instead of tying them to one slice), you can use Redux Toolkit's createAction to define standalone action creators, then have both slices listen to them via extraReducers.
This is great for actions that affect multiple parts of your state:
import { createSlice, createAction } from '@reduxjs/toolkit'; // Define shared action creators first export const loginSuccess = createAction('auth/loginSuccess'); export const logout = createAction('auth/logout'); // First slice: uses shared actions const isAuthenticated = createSlice({ name: 'isAuthenticated', initialState: false, extraReducers: (builder) => { builder.addCase(loginSuccess, () => true); builder.addCase(logout, () => false); }, }); export default isAuthenticated.reducer; // Second slice: also uses the same shared actions const currentUser = createSlice({ name: 'currentUser', initialState: 'john', extraReducers: (builder) => { builder.addCase(loginSuccess, () => 'steve'); builder.addCase(logout, (state) => state); }, }); export const currentUserReducer = currentUser.reducer;
This approach makes it clear that these actions are meant to be used across multiple slices, and avoids tying the action definition to one specific slice.
Why Your Original Code Didn't Work
Just to clarify: when you define a reducer inside a slice's reducers field, Redux Toolkit automatically generates an action creator with a type string like [sliceName]/[reducerName]. So your original isAuthenticated/loginSuccess and currentUser/loginSuccess were two distinct action types—dispatch one, and only the matching slice would react. Using extraReducers lets you bypass that and listen to any action type you want.
Both approaches are fully aligned with Redux Toolkit's best practices, and either will let you achieve your goal of updating multiple states with a single action dispatch.
内容的提问来源于stack exchange,提问作者shiva shukla

