¿Por qué y cuándo necesitamos vincular funciones y controladores de eventos en React?
class SomeClass extends Component{
someEventHandler(event){
}
render(){
return <input onChange={------here------}>
}
}
Veo diferentes versiones de ------here------
la parte.
// 1
return <input onChange={this.someEventHandler.bind(this)}>
// 2
return <input onChange={(event) => { this.someEventHandler(event) }>
// 3
return <input onChange={this.someEventHandler}>
¿En qué se diferencian las versiones? ¿O es sólo una cuestión de preferencia?
Gracias a todos por las respuestas y comentarios. Todos son útiles y recomiendo encarecidamente leer este enlace PRIMERO si está confundido como yo acerca de esto.
http://blog.andrewray.me/react-es6-autobinding-and-createclass/
El enlace no es algo específico de React, sino más bien cómo this
funciona en Javascript. Cada función/bloque tiene su propio contexto, ya que las funciones son más específicas en cuanto a cómo se llaman. El equipo de React tomó la decisión de this
no vincularse a los métodos personalizados de la clase (es decir, no a los métodos integrados como componentDidMount
), al agregar compatibilidad con ES6 (sintaxis de clase).
Cuándo debe vincular el contexto depende del propósito de las funciones; si necesita acceder a accesorios, estado u otros miembros de la clase, entonces deberá vincularlo.
Para su ejemplo, cada uno es diferente y depende de cómo esté configurado su componente.
Pre vinculante a tu clase.
.bind(this)
se utiliza para vincular este contexto a la función de sus componentes. Sin embargo, devuelve una nueva referencia de función en cada ciclo de renderizado. Si no desea vincular cada uso de la función (como en un controlador de clics), puede vincular previamente la función.
a. en tu constructor haz el enlace. alias
class SomeClass extends Component{
constructor(){
super();
this.someEventHandler = this.someEventHandler.bind(this);
}
someEventHandler(event){
}
....
}
b. cree sus funciones personalizadas en las funciones de flecha gruesa de clase. alias
class SomeClass extends Component{
someEventHandler = (event) => {
}
....
}
Enlace de tiempo de ejecución a su clase
Algunas formas comunes de hacer esto.
a. puede envolver la función de controlador de componentes con una función lambda (flecha gruesa) en línea.
onChange={ (event) => this.someEventHandler(event) }
esto puede proporcionar funcionalidad adicional, como si necesita pasar datos adicionales para el controlador de clics <input onChange={(event) => { this.someEventHandler(event, 'username') }>
. Lo mismo se puede hacer conbind
b. Puedes utilizarlo .bind(this)
como se describe arriba.
onChange={ this.someEventHandler.bind(this) }
con parámetros adicionales<input onChange={ this.someEventHandler.bind(this, 'username') }>
Si desea evitar la creación de una nueva referencia de función pero aún necesita pasar un parámetro, es mejor abstraerlo a un componente secundario. Puedes leer mas al respecto aquí
en tus ejemplos
// 1
return <input onChange={this.someEventHandler.bind(this)}>
Esto es solo hacer un enlace del controlador de eventos en tiempo de ejecución a su clase.
// 2
return <input onChange={(event) => this.someEventHandler(event) }>
Otro enlace de tiempo de ejecución a su clase.
// 3
return <input onChange={this.someEventHandler}>
Simplemente está pasando la función como función de devolución de llamada para que se active cuando ocurre el evento de clic, sin parámetros adicionales. ¡Asegúrate de previncularlo!
Para resumir. Es bueno pensar en cómo optimizar tu código, cada método tiene una utilidad/propósito dependiendo de lo que necesites.
¿Por qué vincular una función de React?
Cuando define un componente usando una clase ES6, un patrón común es que un controlador de eventos sea un método en la clase. En JavaScript, los métodos de clase no están vinculados de forma predeterminada. Si lo olvida bind this.someEventHandler
y lo pasa a onChange
, quedará indefinido cuando realmente se llame a la función.
Generalmente, si hace referencia a un método sin ()
después, como onChange={this.someEventHandler}
, debe vincular ese método.
Hay tres formas de vincular su onChange
función al contexto correcto
Primero
return <input onChange={this.someEventHandler.bind(this)}>
En este utilizamos bind
explícitamente la función para que el evento onChange esté disponible como argumento para eventHandler. También podemos enviar algún otro parámetro con tipo de sintaxis como
return <input onChange={this.someEventHandler.bind(this, state.value)}>
Segundo
return <input onChange={(event) => { this.someEventHandler(event) }>
Esta es una sintaxis de ES6, mediante la cual podemos especificar los parámetros que queremos pasar a la someEventHandler
función. Sin embargo, esto es equivalente .bind(this)
. También nos da la flexibilidad de enviar otros atributos junto con el evento como
return <input onChange={(event, value) => { this.someEventHandler(event, value) }>
Tercero
Defina la función someEventHandler usando la función Flecha
someEventHandler = () => {
console.log(this); // now this refers to context of React component
}
An arrow function
no tiene su propio this
, this
se utiliza el valor del contexto de ejecución adjunto y, por lo tanto, la función anterior obtiene el contexto correcto.
o vincularlo en el constructor como
constructor(props) {
super(props);
this.someEventHandler = this.someEventHandler.bind(this);
}
return <input onChange={this.someEventHandler}>
En este método, el evento se adjunta directamente a la someEventHandler
función. No se pueden pasar otros parámetros de esta manera.