We could summarize what happens as follows:
The Parent ( Board ) props and puts his mobile phone ( onChange ) and says: if you want to tell me something, just write me a message, then after a while the child thinks "give me text to the parent ", so that the child pulls out the phone from its properties and the texts" Parent ": this.props.onChange("Thank you for sandwiches") . The parent then receives the message and saves it in his notepad ( state ): this.setState({notes})
Here the child receives the properties (details):
<Note key={note.id} id={note.id} onChange={this.update} onRemove={this.remove}> {note.note} </Note>
When the above path to the render() method of the Board component (via {this.state.notes.map(this.eachNote)} , it looks like Board saying
- "Give a render to the
Note component and give it some properties (details)." - "Name one of these details
onChange , and when it will be called Note later, let me run my own method called update " - "To call this support
onChange , we could call it anything, for example
<Note ... fromParentWithLove={this.update}> ... </Note> , but call her onChange to make it easier to follow our intentions. "
Then we can go to the child component - Note . Note tells itself:
- "Wow, if someone clicks the" Save "button, let them launch my own
save method:" <button onClick={this.save}>Save</button> - "Then, inside my
save method, you can call the onChange function provided to me by my Board parent through the details": this.props.onChange(this.refs.newText.value, this.props.id) "
For reference, below is the code copied from JSBin:
var Note = React.createClass({ getInitialState(){ return {editing: false} }, edit() { this.setState({editing: true}) }, save() { this.props.onChange(this.refs.newText.value, this.props.id) this.setState({editing: false}) }, remove() { this.props.onRemove(this.props.id) }, renderForm() { return( <div className="note"> <textarea ref="newText"></textarea> <button onClick={this.save}>Save</button> </div> ) }, renderDisplay() { return( <div className="note"> <p>{this.props.children}</p> <span> <button onClick={this.edit}>Edit</button> <button onClick={this.remove}>X</button> </span> </div> ) }, render() { return (this.state.editing) ? this.renderForm() : this.renderDisplay() } }) var Board = React.createClass({ propTypes: { count: function(props, propName) { if(typeof props[propName] !== 'number'){ return new Error('the count must be a number') } } }, getInitialState() { return { notes: [ {id:1, note:'Call boook'}, {id:2, note:'Buy Something'}, {id:3, note:'Wash Clothes'}, {id:4, note:'Go Jogging'} ] } }, update(newText, id){ var notes = this.state.notes.map( note => (note.id !== id) ? note: { ...note, note:newText } ) this.setState({notes}) }, remove(id){ var notes = this.state.notes.filter(note => note.id !== id) this.setState({notes}) }, eachNote(note) { return (<Note key={note.id} id={note.id} onChange={this.update} onRemove={this.remove}> {note.note} </Note>) }, render() { return (<div className='board'> {this.state.notes.map(this.eachNote)} </div>) } }) ReactDOM.render(<Board count={10}> </Board>, document.getElementById('react-container'))