reactjs - Reaccionar: ¿Cuál es la flecha recomendada o la función normal?
ecmascript-6 ecmascript-5 (2)
Hay tantas respuestas por ahí, pero la gente siempre se confunde. Lo sé porque me confundí de vez en cuando. Después de algún tiempo, entendí los conceptos.
- Enlazar objeto / función manualmente para jugar con estado o accesorios dentro de la función y evitar problemas relacionados con el alcance
No es exactamente cierto.
No es necesario vincular las funciones para jugar con estado o accesorios.
Enlaza la función con
this
cuando pierdes
this
contexto en el ámbito.
Por ejemplo, en una función de devolución de llamada.
class App extends React.Component {
state = {
name: "foo",
}
aFunction() {
console.log( this.state.name );
}
render() {
return <div>{this.aFunction()}</div>;
}
}
No necesita vincular su función ya que
this
apunta a su clase y no pierde su contexto.
Pero si usa su función en una devolución de llamada como un botón, tiene que enlazarla:
class App extends React.Component {
state = {
name: "foo",
}
aFunction() {
console.log( this.state.name );
}
render() {
return (
<div>
<button onClick={this.aFunction}>Click</button>
</div>
);
}
}
Esto no funciona ya que se pierde el contexto. Ahora, necesitas recuperar su contexto de alguna manera, ¿no? Ok, veamos como podemos hacer esto. Primero, quiero enlazarlo en el callback del botón.
<button onClick={this.aFunction.bind(this)}>Click</button>
Sí, esto funciona. Pero, será recreado en cada render. Asi que:
- Enlazar objeto / función siempre en el constructor pero no directamente en el render
Sí. No lo ate como lo hice arriba, hágalo en su constructor.
Si lo hace en el constructor, Webpack crea un nuevo objeto / función en el archivo bundle.js solo una vez cuando el componente se procesa por primera vez.
Si lo hace directamente en render, Webpack creará un nuevo objeto / función en el archivo bundle.js cada vez que su componente se renderice y vuelva a renderizar.
Usted está resumiendo aquí lo que he tratado de explicar hasta ahora. Pero, supongo que Webpack no es el que hace esto, su aplicación lo es.
- Si no se enlaza, entonces no puede acceder al estado o accesorios. Debe asignar el objeto actual a una variable local, de lo contrario this.state o this.props no está definido
Nuevamente, si usa su función dentro del alcance de su clase, no tiene que vincularla.
Si usa esta función fuera de su clase, como una devolución de llamada de botón, tiene que enlazarla.
Esto no está relacionado con el
state
o los
props
.
Esto está relacionado con el uso de
this
.
La segunda opción para vincular es realizar la vinculación en el constructor utilizando una función regular y la tercera es usar una función de flecha sin vinculación.
Ahora, la flecha funciona.
1.No es necesario vincular un objeto / función en el constructor ni renderizar
Sí.
- No es necesario depender de los intervalos de variables locales del objeto actual, es decir, dejar que = esto;
Sí.
- No tendrá problemas de alcance y el enlace de objeto / función se realizará automáticamente
Sí.
Pero mi consulta es que escuché que se recomienda usar la función normal y enlazarla en el constructor en lugar de usar la función de flecha porque las funciones de flecha crean un nuevo objeto / función en Webpack bundle.js cada vez que el componente se renderiza y vuelve a renderizar.
Como todos dijeron, eso depende de donde los uses.
render() {
return (
<div>
<button onClick={() => this.aFunction()}>Click</button>
</div>
);
}
Aquí, será recreado en cada render. Pero si no necesita pasarle ningún argumento, puede usarlo como referencia.
render() {
return (
<div>
<button onClick={this.aFunction}>Click</button>
</div>
);
}
Esto funciona como el anterior.
Entonces, si ve un
()
en su método de render, esta función se recrea en cada render.
Regular o una flecha, no importa.
Si lo estás invocando de alguna manera, entonces lo estás recreando.
Esto se aplica para enlazar en el render como
aFunction.bind(this)
.
Veo
()
allí.
Por lo tanto, utilice las funciones por sus referencias para evitar este problema. Ahora, la gran pregunta es ¿qué sucede cuando necesitamos algunos argumentos? Si usa una función de flecha para pasar un argumento, intente cambiar su lógica.
¿Pero es realmente importante tanto? Como dijo @Eric Kim, la optimización es un problema si realmente lo necesitas. Esta es una sugerencia general ya que he escuchado esto de muchas personas. Pero personalmente, estoy tratando de evitar el uso de funciones si se recrearán en cada render. Pero de nuevo, esto es totalmente personal.
¿Cómo puedes cambiar tu lógica? Estás mapeando una matriz con un elemento y creando un botón. En este botón, está utilizando una función que pasa el nombre del elemento a una función.
{
items.map( item =>
<button onClick={() => this.aFunction(item.name)}>Click</button>
)
}
Esta función se recreará en cada render para cada elemento!
Por lo tanto, cambie su lógica, cree un componente de
Item
separado y asigne un mapa.
Pase el
item
,
aFunction
como props.
Luego, con una función de manejador en este componente, use su función.
const Item = ( props ) => {
const handleClick = () => props.aFunction( props.item.name );
return (
<button onClick={handleClick}>Click</button>
);
}
Aquí, está utilizando un controlador
onClick
con su referencia e invoca su función real.
No se recreará ninguna función en cada render.
Pero, como inconveniente, debe escribir un componente separado y un poco más de código.
Puedes aplicar esta lógica la mayor parte del tiempo. Tal vez haya algunos ejemplos que no puedas, quién sabe. Así que la decisión es tuya.
Por cierto, la publicación de Medium que @widged dio en los comentarios es una discusión famosa sobre este tema. ¿Son las funciones de flecha realmente más lentas que las regulares? Sí. ¿Pero cuanto? No tanto, supongo. Además, esto es cierto para el código transpilado. En el futuro, cuando se conviertan en nativos, serán los más rápidos.
Como una nota lateral personal. Estaba usando las funciones de flecha todo el tiempo ya que me gustan. Pero hace un rato en una discusión, dijo alguien.
Cuando veo una función de flecha en la clase, pienso que: ''Esta función se está usando / llamando fuera de esta clase''. Si veo uno normal, entiendo que esta función se llama dentro de la clase.
Me gustó mucho este enfoque y ahora, si no necesito llamar a mi función fuera de mi clase, estoy usando uno normal.
Comencé a usar las funciones de flecha después de sentir que hacer la función manual / los enlaces de objetos y los problemas relacionados con el alcance son un dolor de cabeza, pero muy recientemente me di cuenta de que es mejor usar la función normal (ES5) que la función de flecha (ES6).
Mi comprensión acerca de estas funciones
Función normal en reaccionar:
- Enlazar objeto / función manualmente para jugar con estado o accesorios dentro de la función y evitar problemas relacionados con el alcance
- Enlazar objeto / función siempre en el constructor pero no directamente en el render
- Si lo hace en el constructor, Webpack crea un nuevo objeto / función en el archivo bundle.js solo una vez cuando el componente se procesa por primera vez.
- Si lo hace directamente en render, Webpack creará un nuevo objeto / función en el archivo bundle.js cada vez que su componente se renderice y vuelva a renderizar.
- Si no se enlaza, entonces no puede acceder al estado o accesorios. Debe asignar el objeto actual a una variable local, de lo contrario this.state o this.props no está definido
Función de flecha en reaccionar:
- No es necesario enlazar un objeto / función en el constructor ni renderizar
- No es necesario depender de los intervalos de variables locales del objeto actual, es decir, dejar que = esto;
- No tendrá problemas de alcance y el enlace de objeto / función se realizará automáticamente
Pero mi consulta es que escuché que se recomienda usar la función normal y enlazarla en el constructor en lugar de usar la función de flecha porque las funciones de flecha crean un nuevo objeto / función en Webpack bundle.js cada vez que el componente se renderiza y vuelve a renderizar.
¿Es esto cierto? ¿Cuál es el recomendado?
Este hilo aceptó la respuesta. El uso correcto de las funciones de flecha en React dice -> Depende de dónde está usando exactamente la función de flecha. Si la función de flecha se utiliza en el método de representación, creará una nueva instancia cada vez que se llame a la representación, de la misma forma en que funcionaría el enlace.
Lo siento si sientes que es una pregunta teatral, pero esta es mi mayor duda. Sugerir amablemente
Si tienes siguiendo el código React,
class A extends React.Component {
constructor(props) {
super(props)
this.state = {name: props.name}
}
render() {
return (
<button onclick={(event)=>console.log(this.state.name)} />
)
}
}
cambiar a seguir
class A extends React.Component {
state = {name: this.props.name}
render() {
return (
<button onclick={this.logName} />
)
}
logName = (event) => {
console.log(this.state.name)
}
}
De esta manera, no está creando nuevas funciones anónimas en cada render.
La nueva instancia de la función se crea cada vez que se ejecuta el código
()=>
, esto no es
magic
.
Echa un vistazo a las siguientes funciones miembro
class A {
memberFuncWithBinding = () => {}
memberFuncWithoutBinding(){}
}
Ambas funciones miembro solo se crean una vez, cuando se crea una instancia de la clase. Nuevamente, no se prefiere la función mágica, pero se prefiere la función de miembro superior, ya que cuando se usa dentro de esa función, tendrá la clase A correcta en este enlace.
EDITAR: Mire, NO intente optimizar su código antes de que tenga problemas. la creación de nuevas funciones cada render es más lenta pero solo por una fracción de milisegundo.