Tengo dos React Componentes: Primero:
class Clock extends React.Component { constructor(props){ super(props); this.state = {date: new Date()}; } componentDidMount() { this.timerID = setInterval( () => this.tick(),1000); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } render() { return ( <div style={{border:"1px solid black"}}> <h1 style={{color:"blue"}}> Component Clock has been rendered </h1> <h2> Time: {this.state.date.toLocaleTimeString()}</h2> </div> ); } };Y segundo:
class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(prevState => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'On' : 'Off'} </button> ); } } En el segundo componente, no funciona hasta que vinculo handleClick() a this . Pero funciona perfectamente en el primer caso, aunque no he usado bind() . No puedo entender cuál es el problema =(. Parece que en el primer componente captura automáticamente this , ¿cómo sucede?
En el primer ejemplo, solo funciona porque usó una función de flecha como la devolución de llamada setInterval que vinculaba el this de la función de llamada, componentDidMount para estar vinculado a la devolución de llamada () => this.tick() que es el correcto esperado this en el función de tick cuando se llama.
En otras palabras, si hubieras hecho:
componentDidMount() { this.timerID = setInterval(this.tick, 1000); } Vería el TypeError: this.setState is not a function ya que el componente this está vinculado a la función interna.
También podría vincular this al pasar la devolución de llamada a `setInterval:
componentDidMount() { this.timerID = setInterval(this.tick.bind(this), 1000); } En el segundo ejemplo, el controlador onClick={this.handleClick} no funciona hasta que el componente this se haya vinculado al controlador. Esto se hace de varias maneras:
Encuadernado en constructor ( como en los viejos tiempos )
class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; this.handleClick = this.handleClick.bind(this); // <-- here } handleClick() { this.setState((prevState) => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? "On" : "Off"} </button> ); } }Vinculado al pasar la devolución de llamada
class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; } handleClick() { this.setState((prevState) => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <button onClick={this.handleClick.bind(this)}> // <-- here {this.state.isToggleOn ? "On" : "Off"} </button> ); } }Usando la función de flecha.
class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; } handleClick = () => { // <-- here as arrow function this.setState((prevState) => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? "On" : "Off"} </button> ); } }