In the process of using react, the execution result is not as expected because of this problem of function. Now, to sort out the following problems, first look at the code:
import React from "react"; class MsgList extends React.PureComponent { render() { return ( <ul> {this.props.list.map((item, index) => (<li key={index}>{item}</li>))} </ul> ) } } export default class List extends React.Component { constructor(props) { super(props) this.state = { inputMsg: '', list: [123] } } handleInput = (val) => { this.setState({ inputMsg: val.target.value }) } handleSubmit = () => { const text = this.state.inputMsg if (text) { const msg = [...this.state.list, text] this.setState({ inputMsg: '', list: msg }) } } render() { return ( <div> <MsgList list={this.state.list}/> <input type="text" value={this.state.inputMsg} onChange={this.handleInput}/> <button onClick={this.handleSubmit}>Submission</button> </div> ) } }
The sample code implements simple element addition and list display functions.
Function binding and definition are as follows:
// binding onChange={this.handleInput} // Definition handleInput = (val) => { this.setState({ inputMsg: val.target.value }) }
There are many ways to define functions, such as:
handleInput(val) { console.log(val.target) console.log(this) this.setState({ inputMsg: val.target.value }) }
At this time, val.target is the < input > element, but this is undefined. At this time, calling this.setState will report an error.
Class will not bind this by default, so the context of function execution is lost here. If you add a pair of parentheses when Binding:
<input type="text" value={this.state.inputMsg} onChange={this.handleInput()}/> // Function definition handleInput(val) { console.log(val.target) console.log(this) this.setState({ inputMsg: val.target.value }) }
At this time, add brackets. Although the context is bound, this will cause the function to be triggered when the component renders, rather than by clicking when the rendering is finished, and the onChange action cannot be responded to. Components trigger functions in rendering process. Calling setState() in function calls render again, resulting in a dead loop.
If. bind() is used as the binding context of the function at the beginning, remove the brackets when binding the function,
constructor(props) { super(props) this.state = { inputMsg: 'hello', list: [123] } this.handleInput = this.handleInput.bind(this) }
At this time, the function is normal.
In the beginning, we used arrow function to bind context when defining function, so we can also achieve the desired function.
In addition, there's another way of writing that works, but it's actually the same as the first one.
<input type="text" value={this.state.inputMsg} onChange={(e)=>this.handleInput(e)}/>
Summary
When using react, you should pay attention to the direction of this. By default, a class will not bind this to a method, either manually bind this at the beginning, or use the arrow function to automatically bind the context. If it is not a function that you want to trigger when the component renders, you cannot bind the function with parentheses.