react-final-form: Warning: Cannot update a component from inside the function body of a different component.
Are you submitting a bug report or a feature request?
bug report
What is the current behavior?
After npm upgrading to the latest React, I am getting the following warning in my console from the React Developer tools Chrome extension: “Warning: Cannot update a component from inside the function body of a different component.”
The component trace just points to a line with a boring/standard use of Field in JSX. Quickly going through the app I’m working on, this warning happens everywhere, on every use of Field in the app. For example, the warnings point to lines like the 2nd to last line (RadioField = ...) of this file (please excuse the coding style here). Again, there is nothing special about this code; it’s happening on every Form that has components that use Field.
import React from "react";
import { Field } from "react-final-form";
const Radio = ({label,input,children,className}) => {
const { checked } = input;
return (
<label className={"input-radio "+ (checked? "is-checked ": "")+
className}>
{children && children}
<input
{...input}
className="form-radio"
/>
<var title={label}>{label}</var>
</label>
);
};
Radio.defaultProps = { label:"", meta:{}, input:{}, children:[] };
const RadioField = props => <Field {...props} component={Radio} type="radio"/>;
export default RadioField;
What is the expected behavior?
No warning
Sandbox Link
I’ll make one if you need it, but I think the link below in Other Information succinctly explains what is happening and a hooks based workaround that react-final-form can implement.
What’s your environment?
ChromeOS 79 React 16.13.0 released Feb 26th, 2020 Final Form 4.18.7 React Final Form 6.3.5
Other information
See here: https://reactjs.org/blog/2020/02/26/react-v16.13.0.html#warnings-for-some-updates-during-render
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 48
- Comments: 49 (14 by maintainers)
I’m also seeing this warning after updating to React 16.13.0. For me, it only seems to occur when a field is conditionally rendered.
Sandbox link: https://codesandbox.io/s/empty-forest-6m0ri?fontsize=14&hidenavigation=1&theme=dark
Hi guys. Sorry to be so late on this. I got laid off at work and have had two children locked in the house with me for weeks.
A lot have work has been done to ensure that things look right “on first render”, which is why things are the way they are. This is going to be a major breaking change. I just tried it and 75% of the unit tests failed.
Yep.
This needs more investigation.
Published fix in
v6.4.0andfinal-form@4.19.0.Summary:
useField()was doing a quick subscribe-and-unsubscribe of the field on first render to get the initial state. Reactv16.13.xdoesn’t like this, as it was callingsetState()in the containing<Form/>component. So I’ve added asilentflag toform.registerField()which allows this register-unregister trick to happen without any ripples going out to other subscribers. This solves the problem.That means “only notify listeners to this one field”. It doesn’t seem to have any other usages, so it’s vestigial from an earlier time, but it’s just what was needed in this case.
Yes. The rest of the times, it really does need to notify all the other fields, as they can depend on each other.
A copy of the fields structure must be made to iterate through, since some of the things that get called can result in fields being unregistered.
A good example of this happening is the Wizard Form Example. Any time the Previous or Next buttons are pressed, just about every Field from all pages throws this warning.
I have some good news for you guys…
Published fix in
final-form@4.19.1. It fixes that sandbox, @yann-combarnous.I did some analysis on this issue and found the source of the problem, at least for conditionally rendered fields, but this might also be the cause in other cases:
https://github.com/final-form/react-final-form/blob/f3c1aea93b520c0620f1b8090f5966e0da94a798/src/useField.js#L90-L105
In here, the field is synchronously registered, which causes a synchronous update to the form state, which in turn synchronously triggers
setState()on theForm:https://github.com/final-form/react-final-form/blob/f3c1aea93b520c0620f1b8090f5966e0da94a798/src/ReactFinalForm.js#L97
So what it boils down to is that the mounting of a
Fielddirectly callssetState()on theForm. This is apparently not a problem in some cases, but in others. I’ll have to do some additional analysis to figure how how to rewrite that code to useuseEffect()instead. If anyone else already has a good idea, just reply, I’ll keep a close eye on this thread.Same here, i’ve upgraded to the newest versions of final-form and the issue still remains.
I’m still having issues with the new version, also using fields with validation.
@erikras I noticed that the
silenttrick does not work for fields with validators since during the unsubscribe, line 902 still runs https://github.com/final-form/final-form/blob/64225dd3589020297c5e23209630ac31afd46c5c/src/FinalForm.js#L902Don’t understand how an elite developer like you would be laid off, even now… Also, try Upwork. With your resume, you should be making a lot of money immediately working remotely.
On Mon, Mar 30, 2020, 6:46 AM Erik Rasmussen notifications@github.com wrote:
No worries, everything will be fine @erikras . 🍻
Yeah, I’m gonna get a job quickly; have several offers already, but it still adds additional stress to the already elevated global level.
Companies restructure and my position disappeared out from under me. Wasn’t to do with my performance or skill level.
A lot of popular libraries are affected by this warning : https://github.com/facebook/react/issues/18178 It’s a warning party in my console right now as I also use urql which is affected as well. 😂
Yes, I got this error for a select box that is dynamically rendered.
I have created a generic dropdown menu component using (Material-Ui Autocomplete), so I can use where I need. But I am facing a warning,
“Warning: Cannot update a component (
ProductSubCategory) while rendering a different component (ForwardRef(Autocomplete)). To locate the bad setState() call insideForwardRef(Autocomplete)”Note
I followed different links but couldn’t get the proper answer I have a slightly different scenario. I have created a generic dropdown menu component and use inside other components where needed.
Here is code of dropdown menu component `
Here is the code of Component in which I am using dropdown menu component
`
`
Not a fix. But i realized that when i added the
subscriptionprop to the form: (subscription={{ submitting: true, pristine: true }}in my case) The errors disappeared.I have the same issue with ff 4.19.1 and rff 6.5.0. I have not found a way to read the form state from outside my component safely. Is there a workaround?
I’m seeing this when using
useFieldin conjunction with a select field built withdownshift. Using the latest version of both packages.I’ve solved it temporarily by wrapping the offending function in
setTimeout:Larger section of code for context:
@atuttle yep I have the very same error with checkbox adding a new Field. 😃
I have seen a reduction in these errors in my app, but they are not completely eliminated.
I have a form that shows some assumed values and gives the user the option to edit them by clicking on a link to make the form fields appear. Previously, that click would throw a couple of these errors (I think 2 or 3? odd since there are 5 fields). Those errors no longer appear. However, that form also includes a checkbox that, when toggled a certain way, adds an additional field. Adding that additional field is still throwing the error.
I’m not a frequent user of CodeSandbox, but hopefully I’ve done this right. The sandbox from @jsalis demonstrated my issue (checkbox to make field appear) so I forked it and updated the final-form version to 4.19.1, and the error still happens there: https://codesandbox.io/s/react-16130-final-form-warning-tnid2
Thanks @erikras . Still getting one scenario where this error shows up, it seems. Seems to happen on submit when form.registerField is used. Replacing it with OnChange from react-final-form-listeners also seems to not trigger the error.
Will try and narrow down the specific pattern, have made a short try today at a CodeSandbox, with no luck so far. Stack trace: