I have a form with three fields, the handleChange method works in the first field (DateOfBirth) but not in the (Id1) and (Id2) fields.
For some reason setState return this error when i try to change the value of the (Id1||Id2) fields.
"A component is changing a controlled input of type text to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component"
import React, { Component } from 'react';
class Form extends React.Component {
constructor(props){
super(props);
this.state = { DateOfBirth:'1990-01-24', Metadata: {Id1:'33813518109', Id2:'John Doe'}}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
const target = event.target;
const name = target.name;
var value = target.value;
if(name === "Id1" || name === "Id2")
this.setState({Metadata:{[name]: value}});
else
this.setState({[name]: value});
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input name="DateOfBirth" type="date" onChange={this.handleChange} value={this.state.DateOfBirth} />
<input name="Id1" type="text" onChange={this.handleChange} value={this.state.Metadata.Id1} />
<input name="Id2" type="text" onChange={this.handleChange} value={this.state.Metadata.Id2} />
</form>
</div>
);
}
}
export default Form;
Before updating the value of the state, we need to build an initial state setup. Once we are done with it, we use the setState() method to change the state object. It ensures that the component has been updated and calls for re-rendering of the component.
To update an array of objects state in React: Use the map() method to iterate over the array. On each iteration, check if a certain condition is met. Update the properties of the object that matches the condition.
From react docs.
The output of the updater is shallowly merged with prevState.
Which means when you do
// name === 'Id1'
// value === 'dummy'
this.setState({Metadata:{[name]: value}});
then Metadata
key in the state will have this shape:
{
Metadata: {
Id1: "dummy"
}
}
Do you see the problem? Now input with Id2
receives as value undefined
(this.state.Metadata.Id2
doesn't exist) which will make react throw an error about an uncontrolled component.
What you need to do to fix it is to make a full copy of nested object properties:
this.setState(prevState => ({
Metadata:{
...prevState.Metadata,
[name]: value
}
}));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With