FormSpy - Cannot update a component while rendering a different component
See original GitHub issueAre 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:
- Created 3 years ago
- Reactions:23
- Comments:13
Top 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 >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
The issue still persists with
react-final-form@6.5.1
andfinal-form@4.20.1
with react version16.13.1
. Here’s what I’ve found after digging through the (compiled) library source:useField()
is invoked internally by thereact-final-form
library from within theField
component.useState()
hook. This parametrizes the internalregister()
function with atrue
second argument which is thesilent
flag. All is fine at this point.final-form
goes into a validation loop. I see in the stack trace that it invokesrunValidation()
which in turn leads tonotifyFieldListeners()
and then tonotifySubscribers()
on each field. This actually brings the code path back toreact-final-form
, into theuseEffect()
call inside of which the field is registered again but this time without thesilent
flag.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.
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 cheekysetTimeout(,0)
. Hacky, stochastic, but it is working at least. Defo not a solution long term but thought I’d share 😃