Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

update depth exceeded using redux form

I am trying to get validate redux-form dependent on drop-down value selection, below are the code and error.

I am getting Uncaught Error: 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.

Please help me and Thanks in advance

    ...
      <Field
        id="user-form-email"
        name="email"
        component={emailField}
        className={style.inputField}
        fullWidth
        label={i18n({ id: "users.email" })}
        validate={[emailRequiredForAdmin("role")]}
        disabled={selectedRole === "manager"}
      />

      <Field
        id="user-form-roles"
        name="role"
        component={userRoleSelectField}
        className={style.inputField}
        fullWidth={true}
        items={getRoles(intl)}
        label={i18n({ id: "users.role" })}
        onChange={(event) => {
          if (event.target.value == "user") {
            this.props.change("password", "");
            this.props.change("confirmPassword", "");
          }
        }}
      />
    ...

// Decorate with redux-form

UsersForm = reduxForm({
  form: formNames.USER,
})(UsersForm);

const selector = formValueSelector(formNames.USER);

UsersForm = connect((state) => {
  const selectedRole = selector(state, "role");
  return {
    selectedRole,
  };
});

Errors:

    The above error occurred in the <Form(Connect(UsersForm))> component:
    in Form(Connect(UsersForm)) (created by ConnectFunction)
    in ConnectFunction (created by Connect(Form(Connect(UsersForm))))
    in Connect(Form(Connect(UsersForm))) (created by ReduxForm)
    in ReduxForm (created by Context.Consumer)
    in Hoc (created by ReduxForm)
    in ReduxForm (created by ConnectFunction)
    in ConnectFunction (created by Users)
    in Users (created by ConnectFunction)
    in ConnectFunction (created by _temp)
    in _temp (created by Context.Consumer)
    in Route (created by App)
    in Switch (created by App)
    in div (created by RoutesContainer)
    in RoutesContainer (created by App)
    in div (created by Container)
    in Container (created by App)
    in div (created by Layout)
    in Layout (created by App)
    in div (created by App)
    in App (created by Context.Consumer)
    in Route (created by RootApp)
    in Switch (created by RootApp)
    in MuiPickersUtilsProvider (created by RootApp)
    in ThemeProvider (created by RootApp)
    in Router (created by ConnectedRouter)
    in ConnectedRouter (created by Context.Consumer)
    in ConnectedRouterWithContext (created by ConnectFunction)
    in ConnectFunction (created by RootApp)
    in Provider (created by RootApp)
    in RootApp (created by LocalizedApp)
    in IntlProvider (created by LocalizedApp)
    in LocalizedApp

    Uncaught Error: 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.
        at checkForNestedUpdates (react-dom.development.js:23093)
        at scheduleUpdateOnFiber (react-dom.development.js:21164)
        at dispatchAction (react-dom.development.js:15660)
        at Subscription.checkForUpdates (connectAdvanced.js:101)
        at Subscription.handleChangeWrapper (Subscription.js:100)
        at eval (Subscription.js:26)
        at batchedUpdates$1 (react-dom.development.js:21856)
        at Object.notify (Subscription.js:22)
        at Subscription.notifyNestedSubs (Subscription.js:95)
        at Subscription.checkForUpdates (connectAdvanced.js:90)
like image 530
avi Avatar asked Nov 14 '22 21:11

avi


1 Answers

You should not call a function inside validate array. Do it like this instead.

    // Outside of the component, if possible: 
    const emailRequiredForAdminValidator = emailRequiredForAdmin("role")

    // Or useMemo if you need component state, and you have to put any
    // value used in the `emailRequiredForAdmin` in that `useMemo` deps array
    const emailRequiredForAdminValidator = useMemo(() => 
      emailRequiredForAdmin("role")
    , [/* deps here */]);
    
    <Field
        id="user-form-email"
        name="email"
        component={emailField}
        className={style.inputField}
        fullWidth
        label={i18n({ id: "users.email" })}
        validate={[emailRequiredForAdminValidator]}
        disabled={selectedRole === "manager"}
      />

This is because every time the component is re-rendered the function userRoleSelectField is called again, and that causes the component to re-render again, thus causing an infinite loop.

Basically, as pointed out by @diedu, any function called at render, (such as userRoleSelectField, emailField or emailRequiredForAdminValidator...) and that cause another render, for example by calling setState, will result in a call stack overflow.

like image 187
Nitin Garg Avatar answered Jan 29 '23 21:01

Nitin Garg