Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to call a reducer function from another reducer function (within the same slice) using Redux Toolkit?

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?

like image 373
Asaf Sitner Avatar asked Aug 24 '20 15:08

Asaf Sitner


People also ask

Can we call a pure function inside a reducer?

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.

Can I mutate state in Redux toolkit?

One of the primary rules of Redux is that our reducers are never allowed to mutate the original / current state values!

What two arguments does a reducer accept?

The reducer takes two parameters: state and action .

What happens when you try to dispatch an action within a reducer?

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.


1 Answers

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.

like image 182
markerikson Avatar answered Oct 12 '22 22:10

markerikson