0

I have a React component which is a dynamic wizard implementing with Redux + ImmerJS. It renders a list of groups (forms) one at a time based on a JSON schema for users to fill in one at a time. Each group has a unique groupCode that can be used as identifier. When users go through the wizard, I need to keep track of the completed/uncompleted state of each group.

The issue is with the implementation of reducing the SET_ACTIVE_GROUP_VALID action below. At run time, it causes this run-time error when filling the form.

Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

I have narrowed it down and pretty sure it is this action that causes the issue because if I commented it out, the error goes away. I have consulted the docs at https://immerjs.github.io/immer/docs/return and I expect what I am doing should work. Where am I missing?

// reducer.js
export const initialState = {
    loading: false,
    schema: {},
    groupsValidity: {},
};

const reducer = (state = initialState, action) =>
    produce(state, draft => {
        switch (action.type) {
            case types.GET_SCHEMA_LOADING:
                draft.loading = true;
                break;
            case types.GET_SCHEMA_SUCCESS:
                draft.loading = false;
                draft.data = action.data;
                break;
            // ..... more actions
            case types.SET_ACTIVE_GROUP_VALID:
                // => this implementation throws run-time ERROR !!!
                draft.groupsValidity[action.groupCode] = { 
                    isCompleted: action.value,
                };                 
                break;
        }
    });

Any help/explanation appreciated.

Sean P.
  • 21
  • 4

1 Answers1

0

I found an alternative that works: use lodash merge.

import { merge } from 'lodash';

.....

    case types.SET_ACTIVE_GROUP_VALID:
                merge(draft.groupsValidity, {
                    [action.groupCode]: {
                        isCompleted: action.value,
                    },
                });  // this works. no run-time error and produce correct state. 

Still good to know why the vanila JS implementation does not work though.

Sean P.
  • 21
  • 4