ref – https://stackoverflow.com/questions/42522515/what-are-react-controlled-components-and-uncontrolled-components
https://reactjs.org/docs/forms.html#controlled-components
A Controlled Component is one that takes its current value through props and notifies changes through callbacks like onChange. A parent component “controls” it by handling the callback and updating its state. It then passes the updated back to the controlled component. You could also call this a “dumb component”.
The parent component’s hold on that single source of data is called “single source of truth”.
In regards to Elements
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; // single source of truth this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } } |
1) Since the value attribute is set to display component’s state, the displayed value will always be this.state.value. This makes React state the single source of truth.
2) Since handleChange runs on every keystroke to update the React state, the displayed value will update as the user types.
3) With a controlled component, the input’s value is always driven by the React state.
With a Textarea, we write it like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
class EssayForm extends React.Component { constructor(props) { super(props); this.state = { value: 'Please write an essay about your favorite DOM element.' }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('An essay was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Essay: <textarea value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } } |
In regards to Components
We have controlled components ListGroup and Pagination. Notice we pass data into them to be processed and displayed. They then use callbacks such as selectedGenre, handlePageChange, handleNoGenre, handleGenreSelect to update parent component Movies’s state.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
class Movies extends Component { state = {...} componentDidMount() { console.log('--componentDidMount--'); } render() { const { ... } = this.state; return ( <div className="row"> <div className="col-2"> <ListGroup items={genres} onItemSelect = {this.handleGenreSelect} selectedItem={this.state.selectedGenre} noGenre = {this.handleNoGenre} /> </div> <div className="col"> <Pagination itemsCount={count} pageSize={pageSize} currentPage = {currentPage} onPageChange={this.handlePageChange} /> </div> </div>) } } |