Reputation: 13105
React warns if you you convert a component from controlled to uncontrolled (or vice versa) during the lifecycle of components.
Besides this being confusing to reason about, are there other technical reasons for which this is not recommended ?
Upvotes: 4
Views: 26482
Reputation: 167
You might have been using an input field with both properties "value={variable1}" & "defaultValue={something}". like this -->
<input
value={mobile}
onChange={(e) => setMobile(e.target.value)}
type="text"
defaultValue="XXXXXXXXXX"
/>
just remove defaultValue attribute. like this -->
<input
value={mobile}
onChange={(e) => setMobile(e.target.value)}
type="text"
/>
That's it. Happy Coding.
Upvotes: 1
Reputation: 13067
Based on my experience, I believe the main reason is to prevent confusion and unexpected behavior (and therefore - bugs).
This warning came since ReactJS 15. In the previous major version - React 14 (technically, React 0.14) - there wasn't such warning.
Therefore, here's a popular misconception which illustrates a possible confusion. I forked your jsfiddle and did the following changes:
value
(empty string) and defaultValue
('hello').No console warnings anymore. Here's the misconception: one might think that the default (initial) value will be 'hello' and then -> since the Input is controlled -> all future value changes will be stored inside the component state.
But that's not the case. The default displayed value is an empty string, not 'hello'. Believe me, for developers which struggle to grasp the idea behind controlled inputs, that will cause confusion. I've experienced it myself!
Therefore, switching back to React 15, you get a nice little warning:
Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
It doesn't tell you the full story why, but at least it directs you where to read and how to solve it. Much better than no warning at all, right? :-)
Upvotes: 1
Reputation: 1171
To directly answer the question asked: Switching back and forth from controlled to uncontrolled is not using the tool as intended and could cause some strange behaviors. As you mention, it would make it hard to understand what is actually happening (which as a programmer, you should be trying to avoid that type of code). Furthermore, I can't think of an instance where switching back and forth is needed or desired. Do you have any examples of where you need this?
There are a few things to note here. If you open the jsfiddle from your comment, you'll notice two warning messages pop up immediately:
Warning:
value
prop oninput
should not be null. Consider using the empty string to clear the component orundefined
for uncontrolled components.Warning: FormPresenter contains an input of type text with both value and defaultValue props. Input elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props.
Putting the jsx here for reference:
<input
type="text"
value={this.state.value}
defaultValue={this.state.defaultValue}
onChange={this.handleChange}
/>
The first warning is telling you there's something wrong with what you're passing as a value, and is why it gives you the error you're asking about (more on this in a minute).
The second warning is telling you that controlled components should only use value
and uncontrolled components should only use defaultValue
. The reason here is if you need to set a default value for a controlled component, you can just default the value you pass to value
. And if you're using an uncontrolled component you only care about setting a default value as you want the browser to manage the current value normally.
So, now when you type in the input, it gives you that third warning:
Warning: FormPresenter is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component
This is linked to the first warning. Because you're defaulting this.state.value
to null
, the input
is not considered controlled. If you change the default to an empty string (''
), you're properly controlling the input and will not get the warning message. jsfiddle updated to show this
Upvotes: 2