Below is the sample code that display a checkbox to wrap content, an text input field, and a counter with a button to increment
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0,
wrapContent: false
}
}
handleAdd = () => {
this.setState({ counter: this.state.counter + 1 });
}
toggleWrap = () => {
this.setState(state => state.wrapContent = !state.wrapContent);
}
wrapContent(content) {
return this.state.wrapContent ?
<div className="bg-secondary p-2">
<div className="bg-light">{content}</div>
</div>
: content;
}
render() {
return this.wrapContent(
<React.Fragment>
<input type="checkbox" checked={this.state.wrapContent} onChange={this.toggleWrap} />
<input className="form-control"/> {/* <--------value disappear after toggling */}
<DisplayCounter counter={this.state.counter} />
<div className="text-center">
<button className="btn btn-primary" onClick={this.handleAdd}>Increment</button>
</div>
</React.Fragment>
);
}
}
class DisplayCounter extends Component {
render() {
return <React.Fragment><div>
<h2>{this.props.counter}</h2>
</div></React.Fragment>
}
}
If I enter some text in the input, click Add button a couple of time and then toggle the checkbox, the value of the input is gone while the value of DisplayCounter
still persists.
What I don't understand is why the input lose its value, isn't that react use virtual dom to minimize the number of DOM updates, so if virtual dom works for DisplayCounter
, why it doesn't work for the uncontrolled form element like input?
understand why uncontrolled input elements lose its input?
The input there is an uncontrolled input
. It keeps the data in itself. When it unmounts, the data gets erased together with him. The next time it appears, it is a fresh new input.
DisplayCounter
keeps its value, because it is a controlled component
, you keep its value in state this.state.counter