marmelab / react-admin

A frontend Framework for single-page applications on top of REST/GraphQL APIs, using TypeScript, React and Material Design
http://marmelab.com/react-admin
MIT License
24.74k stars 5.21k forks source link

TabbedForm has Error: Maximum update depth exceeded #10068

Closed oleksiisurnin closed 2 weeks ago

oleksiisurnin commented 1 month ago

What you were expecting:

I expected the TabbedForm component to render without errors, regardless of the number of TextInput fields.

What happened instead: When using more than 24 TextInput fields in the TabbedForm component, the application throws an error: "Maximum update depth exceeded." This error does not occur with 24 or fewer TextInput fields.

Steps to reproduce: Create a TabbedForm component with at least 25 TextInput fields distributed across multiple tabs. Render the TabbedForm component. Observe the error "Maximum update depth exceeded" in the console.

Related code:

    return (
        <Create>
            <TabbedForm
                tabs={
                    <TabbedFormTabs variant="scrollable" scrollButtons="auto" />
                }
                onSubmit={(e) => {
                    console.log(e)
                }}
            >
                <TabbedForm.Tab label="Tab 1">
                    <TextInput source="field1_1" label="Field 1.1" />
                    <TextInput source="field1_2" label="Field 1.2" />
                    <TextInput source="field1_3" label="Field 1.3" />
                    <TextInput source="field1_4" label="Field 1.4" />
                    <TextInput source="field1_5" label="Field 1.5" />
                </TabbedForm.Tab>
                <TabbedForm.Tab label="Tab 2">
                    <TextInput source="field2_1" label="Field 2.1" />
                    <TextInput source="field2_2" label="Field 2.2" />
                    <TextInput source="field2_3" label="Field 2.3" />
                    <TextInput source="field2_4" label="Field 2.4" />
                    <TextInput source="field2_5" label="Field 2.5" />
                </TabbedForm.Tab>
                <TabbedForm.Tab label="Tab 3">
                    <TextInput source="field3_1" label="Field 3.1" />
                    <TextInput source="field3_2" label="Field 3.2" />
                    <TextInput source="field3_3" label="Field 3.3" />
                    <TextInput source="field3_4" label="Field 3.4" />
                    <TextInput source="field3_5" label="Field 3.5" />
                </TabbedForm.Tab>
                <TabbedForm.Tab label="Tab 4">
                    <TextInput source="field4_1" label="Field 4.1" />
                    <TextInput source="field4_2" label="Field 4.2" />
                    <TextInput source="field4_3" label="Field 4.3" />
                    <TextInput source="field4_4" label="Field 4.4" />
                    <TextInput source="field4_5" label="Field 4.5" />
                </TabbedForm.Tab>
                <TabbedForm.Tab label="Tab 5">
                    <TextInput source="field5_1" label="Field 5.1" />
                    <TextInput source="field5_2" label="Field 5.2" />
                    <TextInput source="field5_3" label="Field 5.3" />
                    <TextInput source="field5_4" label="Field 5.4" />
                    <TextInput source="field5_5" label="Field 5.5" />
                </TabbedForm.Tab>
            </TabbedForm>
        </Create>
    )

Other information:

react-dom.development.js:26793 Uncaught (in promise) 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 throwIfInfiniteUpdateLoopDetected (react-dom.development.js:26793:11)
    at getRootForUpdatedFiber (react-dom.development.js:7627:3)
    at enqueueConcurrentHookUpdate (react-dom.development.js:7518:10)
    at dispatchSetState (react-dom.development.js:13073:16)
    at Object.next (index.esm.mjs:324:13)
    at Object.next (index.esm.mjs:1313:39)
    at eval (index.esm.mjs:2269:25)

Environment

next: 14.2.5 React-admin version: ^5.0.5 Last version that did not exhibit the issue (if applicable): React version: ^18 Browser: All

repo: https://github.com/oleksiisurnin/TabbedForm-MaxUpdateDepth/

adguernier commented 1 month ago

Thanks for the report and reproducible example. I can't reproduce just by rendering the form. However, the error occurred while submitting the form.

After investigation, the culprit seems to be the onSubmit function. Even when extracting the onSubmit function, the error occurs:

export function UserEdit() {
    const onSubmit = (e) => {
      console.log(e);
    };
    return (
      <Create>
        <TabbedForm
          tabs={<TabbedFormTabs variant="scrollable" scrollButtons="auto" />}
          onSubmit={onSubmit}
        >
             {/* ... */}
olesmarola commented 1 month ago

Have the same issue. When I try to use SimpleForm instead of TabbedForm everything is okay.

djhi commented 1 month ago

Even though I haven't managed to understand why it happens, here's a workaround that fixed the issue in the project I made to reproduce it:

<TabbedForm
  tabs={<TabbedFormTabs variant="scrollable" scrollButtons="auto" />}
  onSubmit={(values: any) => {
    console.log("values", values);
    // Return a promise with a settimeout prevent the Maximum update depth exceeded error
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(undefined);
      }, 0);
    });
  }}
>
olesmarola commented 1 month ago

@djhi it doesn't work if you add extra 1 or more inputs: https://share.cleanshot.com/59zjXrjM

olesmarola commented 2 weeks ago

@djhi @oleksiisurnin https://github.com/react-hook-form/react-hook-form/releases/tag/v7.53.0 release fixes an issue, check on your side, please.

ThieryMichel commented 2 weeks ago

I confirm, using react-hook-form 7.53.0 or above fix the issue.

ThieryMichel commented 2 weeks ago

Fixed by react-hook-form 7.53.0