Basically I have to change the status of one slice as per results of an async thunk defined for a different slice. If that is not possible, which would be the recommended approach?
As per ChatGPT recommendation, I tried calling
action.payload.dispatch(increment());
where increment is a reducer from slice "A"
sliceA.js
import { createSlice } from '@reduxjs/toolkit';
const sliceA = createSlice({
name: 'sliceA',
initialState: {
countA: 0,
},
reducers: {
increment: (state) => {
state.countA += 1;
},
},
});
export const { increment } = sliceA.actions;
export default sliceA.reducer;
then in slice "B" I try to call A's increment reducer
sliceB.js
import { createSlice } from '@reduxjs/toolkit';
import { increment } from './sliceA'; // Import the "increment" action from sliceA
const sliceB = createSlice({
name: 'sliceB',
initialState: {
countB: 0,
},
reducers: {
someReducerInSliceB: (state, action) => {
// Your reducer logic for sliceB
},
},
extraReducers: (builder) => {
builder.addCase('exampleAction', (state, action) => {
// Dispatch the "increment" action from sliceA
action.payload.dispatch(increment()); // This will update the countA in sliceA
});
},
});
export const { someReducerInSliceB } = sliceB.actions;
export default sliceB.reducer;
It causes a runtime error: "action.payload.dispatch is not a function".
Reducer functions don't have direct action to the ThunkAPI or dispatch
function. Reducers are pure functions, so they shouldn't have side-effects like dispatching actions. You also are not calling reducer functions, directly, but rather are dispatching actions to the store and the store is calling the root reducer function and passing the current state object and action to it, propagating down the reducer tree to compute the next state value.
If I understand your question correctly you want some state in both slice A and in slice B to update when a "exampleAction" action is dispatched. Slice A can also declare an extra reducer case to handle the same action and apply its own logic.
Example:
const sliceA = createSlice({
name: 'sliceA',
initialState: {
countA: 0,
},
reducers: {
increment: (state) => {
state.countA += 1;
},
},
extraReducers: (builder) => {
builder.addCase('exampleAction', (state, action) => {
state.countA += 1;
});
},
});
If you want to make the code more DRY then you can abstract the reducer function into a single function.
const increment = (state, action) => {
state.countA += 1;
};
const sliceA = createSlice({
name: 'sliceA',
initialState: {
countA: 0,
},
reducers: {
increment,
},
extraReducers: (builder) => {
builder.addCase('exampleAction', increment);
},
});