I have this small module management slice:
const WorkspaceSlice = createSlice({
name: "workspace",
initialState: {
activeModule: null,
modules:
{
["someModule"]: { ...moduleRenderingData },
},
},
reducers: {
setActiveModule(state, action)
{
state.activeModule = action.payload;
},
addModule(state, action)
{
const { moduleName, renderingData } = action.payload;
if (!state.modules[moduleName])
{
state.modules[moduleName] = renderingData;
}
// state.activeModule = moduleName; <- basically the same as 'setActiveModule'
this.setActiveModule(state, action.payload.module); // <- 'this' is undefined
},
},
});
export default WorkspaceSlice;
What I'm trying to do is call setActiveModule
from within addModule
so that I won't have duplicate code, but I get an error because this
is undefined.
Is there a way to call one reducer from within another? What's the syntax for that?
If not, is it possible to achieve this functionality in another way, assuming I want to keep both addModule
and setActiveModule
as separate actions?
Reducers are pure functions that take in a state and action and return a new state. A reducer should always follow the following rules: Given a set of inputs, it should always return the same output. No surprises, side effects, API calls, mutations.
One of the primary rules of Redux is that our reducers are never allowed to mutate the original / current state values!
The reducer takes two parameters: state and action .
Dispatching an action within a reducer is an anti-pattern. Your reducer should be without side effects, simply digesting the action payload and returning a new state object. Adding listeners and dispatching actions within the reducer can lead to chained actions and other side effects.
The slice
object returned from createSlice
includes each of the individual case reducer functions you passed in as slice.caseReducers
, to help with situations like this.
So, you could do:
addModule(state, action) {
const { moduleName, renderingData } = action.payload;
if (!state.modules[moduleName]) {
state.modules[moduleName] = renderingData;
}
WorkspacesSlice.caseReducers.setActiveModule(state, action);
},
Also, reducer functions have no this
, because there are no class instances involved. They're just functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With