question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

FormSpy - Cannot update a component while rendering a different component

See original GitHub issue

Are you submitting a bug report or a feature request?

bug report

What is the current behavior?

When using FormSpy, the onChange is called during rendering, and throws an error if you use setState.

<FormSpy
  subscription={{ values: true }}
  onChange={change => {
    // fired during rendering, calling a `useState` setter fails
    setValues(change.values);
  }}
/>
Warning: Cannot update a component (`App`) while rendering a different component (`FormSpy`). To locate the bad setState() call inside `FormSpy`, follow the stack trace as described in https://fb.me/setstate-in-render
    in FormSpy (at App.js:23)
    in form (at App.js:13)
    in ReactFinalForm (at App.js:10)
    in App (at src/index.js:9)
    in StrictMode (at src/index.js:8)

What is the expected behavior?

No error.

Sandbox Link

https://codesandbox.io/s/react-final-form-formspy-hltnv?file=/src/App.js

What’s your environment?

    "final-form": "4.20.0",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-final-form": "6.5.0",

Other information

The issue seems to be that onChange in the useFormState is called in the useState init function, which means during rendering: https://github.com/final-form/react-final-form/blob/464f1c7855e93899630df0ad897c322995601849/src/useFormState.js#L26

This is part of a range of error messages introduced in react 16.13, and related to an existing issue (https://github.com/final-form/react-final-form/issues/751)

A workaround would be to put any setState on the onChange in a setTimeout(... ,0), but this feels like a hack, and not clear to new users.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:23
  • Comments:13

github_iconTop GitHub Comments

24reactions
szankriszcommented, Aug 7, 2020

The issue still persists with react-final-form@6.5.1 and final-form@4.20.1 with react version 16.13.1. Here’s what I’ve found after digging through the (compiled) library source:

  1. useField() is invoked internally by the react-final-form library from within the Field component.
  2. It registers the field from within the lazy initializer function of a useState() hook. This parametrizes the internal register() function with a true second argument which is the silent flag. All is fine at this point.
  3. However, despite the silent setting, final-form goes into a validation loop. I see in the stack trace that it invokes runValidation() which in turn leads to notifyFieldListeners() and then to notifySubscribers() on each field. This actually brings the code path back to react-final-form, into the useEffect() call inside of which the field is registered again but this time without the silent flag.
  4. The actual culprit is:
    React.useEffect(function () {
      return register(function (state) {
        if (firstRender.current) {
          firstRender.current = false;
        } else {
          setState(state);
        }
      }, false);
    }
    

I think the following happens: from the aspect of one particular field, registration indeed happens properly (first with the silent and then without the silent flag) but other fields could have completed this cycle already. So, when a field gets initialized it runs into the validation loop, causing the setState() call to take place inside other fields, thereby violating the rule.

I have no suggestion at this point as to how it could be solved though.

7reactions
theZapprcommented, Mar 28, 2021

Hi all, I have been battling this issue while migrating from Redux-Form to React-Final-Form. Redux-Form has isDirty() in its API so I could easily get the state of a Form and use it in another (external) component. The only similar thing I can find for Final Form is FormSpy ( if not please let me know! ). In the end I had to give up and push the “dirty” flag into redux (in effect, rolling my own isDirty() for final-form) : which is when I bumped into the issue you are talking about here.

So far the only way I can get rid of the Warning is by wrapping the redux dispatch call in a cheeky setTimeout(,0). Hacky, stochastic, but it is working at least. Defo not a solution long term but thought I’d share 😃

   // passed to FormSpy's onChange
   onChange = ({dirty}) => {
    // dodgy workaround to avoid Warning :P
    setTimeout(()=>this.props.dispatch( formActions.changed({dirty}) ) ,0)
  }
Read more comments on GitHub >

github_iconTop Results From Across the Web

How to fix the "cannot update a component while rendering a ...
While working on a React / Next.js application I got this error: Cannot update a component (`App`) while rendering a different component.
Read more >
Cannot update a component while rendering a different ...
The problem is when one component queues an update in another component, while the first component is rendering. In other words, don't do...
Read more >
Cannot update a component while rendering a different ...
The other day I encountered an issue where React complained that it cannot update a component while rendering a different component.
Read more >
react cannot update component while rendering a different ...
Warning: Cannot update a component (`HomeInfoCard`) while rendering a different component (`StackCount`). To locate the bad setState() call inside ...
Read more >
Cannot update a component while rendering a ... - YouTube
JavaScript : Cannot update a component while rendering a different component warning [ Gift : Animated Search Engine ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found