He estado leyendo un montón de react
código y veo cosas como esta que no entiendo:
handleChange = field => e => {
e.preventDefault();
/// Do something here
}
He estado leyendo un montón de react
código y veo cosas como esta que no entiendo:
handleChange = field => e => {
e.preventDefault();
/// Do something here
}
Respuestas:
Esa es una función curry
Primero, examine esta función con dos parámetros ...
Aquí está de nuevo en forma de curry ...
Aquí está el mismo código 1 sin funciones de flecha ...
Concentrarse en
return
Puede ser útil visualizarlo de otra manera. Sabemos que las funciones de flecha funcionan así: prestemos especial atención al valor de retorno .
Entonces, nuestra
add
función devuelve una función : podemos usar paréntesis para mayor claridad. El texto en negrita es el valor de retorno de nuestra función.add
En otras palabras,
add
algún número devuelve una funciónLlamar a funciones curry
Entonces, para usar nuestra función de curry, tenemos que llamarlo un poco diferente ...
Esto se debe a que la primera llamada a la función (externa) devuelve una segunda función (interna). Solo después de llamar a la segunda función, realmente obtenemos el resultado. Esto es más evidente si separamos las llamadas en dos líneas ...
Aplicando nuestra nueva comprensión a su código
Bien, ahora que entendemos cómo funciona, veamos tu código
Comenzaremos por representarlo sin usar las funciones de flecha ...
Sin embargo, debido a que las funciones de flecha se unen léxicamente
this
, en realidad se vería más así ...Quizás ahora podamos ver lo que esto está haciendo más claramente. La
handleChange
función está creando una función para un determinadofield
. Esta es una técnica práctica de React porque debes configurar tus propios oyentes en cada entrada para actualizar el estado de tus aplicaciones. Al usar lahandleChange
función, podemos eliminar todo el código duplicado que resultaría en la configuración dechange
escuchas para cada campo. ¡Frio!1 Aquí no tuve que vincular léxicamente
this
porque laadd
función original no usa ningún contexto, por lo que no es importante preservarla en este caso.Aún más flechas
Se pueden secuenciar más de dos funciones de flecha, si es necesario:
Las funciones curry son capaces de sorprender. A continuación vemos
$
definido como una función currificada con dos parámetros, pero en el sitio de la llamada, parece que podemos suministrar cualquier número de argumentos. El curry es la abstracción de la aridad .Aplicación parcial
La aplicación parcial es un concepto relacionado. Nos permite aplicar parcialmente las funciones, de forma similar al currículum, excepto que la función no tiene que definirse en forma de currículum.
Aquí hay una demostración funcional con la
partial
que puedes jugar en tu propio navegador:fuente
$
se usó para demostrar el concepto, pero puedes nombrarlo como quieras. Casualmente pero completamente sin relación,$
se ha utilizado en bibliotecas populares como jQuery, donde$
es una especie de punto de entrada global a toda la biblioteca de funciones. Creo que también se ha usado en otros. Otro que verá es_
, popularizado en bibliotecas como subrayado y lodash. Ningún símbolo es más significativo que otro; Usted asigna el significado de su programa. Es simplemente JavaScript válido: D$
cómo se usa. Si está preguntando acerca de la implementación en sí,$
es una función que recibe un valorx
y devuelve una nueva funciónk => ...
. Al observar el cuerpo de la función devuelta, vemosk (x)
que sabemosk
que también debe ser una función, y cualquiera que sea el resultadok (x)
se vuelve a poner$ (...)
, lo que sabemos devuelve otrak => ...
, y continúa ... Si todavía quedarse atascado, hágamelo saber.abc(1,2,3)
es menos que ideal queabc(1)(2)(3)
. Es más difícil razonar sobre la lógica del código y es difícil leer la función abc y es más difícil leer la llamada a la función. Antes solo necesitabas saber qué hace abc, ahora no estás seguro de qué funciones sin nombre abc está volviendo a hacer, y dos veces más.Comprender las sintaxis disponibles de las funciones de flecha le dará una idea de qué comportamiento están introduciendo cuando están "encadenados", como en los ejemplos que proporcionó.
Cuando una función de flecha se escribe sin llaves de bloque, con o sin múltiples parámetros, la expresión que constituye el cuerpo de la función se devuelve implícitamente . En su ejemplo, esa expresión es otra función de flecha.
Otra ventaja de escribir funciones anónimas usando la sintaxis de flecha es que están vinculadas léxicamente al alcance en el que están definidas. Desde 'Funciones de flecha' en MDN :
Esto es particularmente pertinente en su ejemplo teniendo en cuenta que se toma de un reaccionarsolicitud. Como señaló @naomik, en React a menudo accedes a las funciones miembro de un componente usando
this
. Por ejemplo:fuente
Un consejo general, si se confunde con alguna de las nuevas sintaxis de JS y cómo se compilará, puede verificar babel . Por ejemplo, copiar su código en babel y seleccionar el preajuste es2015 dará una salida como esta
fuente
Piénselo así, cada vez que ve una flecha, la reemplaza por
function
.function parameters
se definen antes de la flecha.Entonces en tu ejemplo:
y luego juntos:
De los documentos :
fuente
this
.Breve y simple 🎈
Es una función que devuelve otra función escrita de forma breve.
¿Por qué la gente lo hace ?
¿Te has enfrentado cuando necesitas escribir una función que se puede personalizar? ¿O tiene que escribir una función de devolución de llamada que tenga parámetros fijos (argumentos), pero necesita pasar más variables a la función pero evitando las variables globales? Si su respuesta es " sí ", entonces es la forma de hacerlo.
Por ejemplo, tenemos una
button
devolución de llamada con onClick. Y necesitamos pasarid
a la función, peroonClick
acepta solo un parámetroevent
, no podemos pasar parámetros adicionales dentro de este:¡No funcionará!
Por lo tanto, hacemos una función que devolverá otra función con su propio alcance de variables sin ninguna variable global, porque las variables globales son malvadas 😈.
¡Debajo de la función
handleClick(props.id)}
se llamará y devolverá una función y tendráid
su alcance! No importa cuántas veces se presione, los identificadores no se afectarán ni cambiarán entre sí, están totalmente aislados.fuente
El ejemplo en su pregunta es el de un
curried function
que utilizaarrow function
y tiene unimplicit return
para el primer argumento.La función de flecha enlaza léxicamente esto, es decir, no tienen su propio
this
argumento, pero toman elthis
valor del ámbito de aplicaciónUn equivalente del código anterior sería
Una cosa más a tener en cuenta sobre su ejemplo es que se define
handleChange
como una constante o una función. Probablemente lo esté usando como parte de un método de clase y use unclass fields syntax
así que en lugar de vincular la función externa directamente, la vincularía en el constructor de la clase
Otra cosa a tener en cuenta en el ejemplo es la diferencia entre el retorno implícito y explícito.
Arriba hay un ejemplo de retorno implícito, es decir. toma el campo de valor como argumento y devuelve el resultado
field*2
que especifica explícitamente la función a devolverPara un retorno explícito, le diría explícitamente al método que devuelva el valor
Otra cosa a tener en cuenta sobre las funciones de flecha es que no tienen las suyas propias,
arguments
sino que también las heredan del ámbito de los padres.Por ejemplo, si solo define una función de flecha como
Como alternativa, las funciones de flecha proporcionan los parámetros de descanso que puede usar
fuente
Puede que no esté totalmente relacionado, pero dado que la pregunta mencionada reacciona usa el caso (y sigo tropezando con este hilo SO): hay un aspecto importante de la función de doble flecha que no se menciona explícitamente aquí. Solo se nombra la 'primera' flecha (función) (y por lo tanto 'distinguible' por el tiempo de ejecución), las flechas siguientes son anónimas y desde el punto de vista de React cuentan como un objeto 'nuevo' en cada render.
Por lo tanto, la función de doble flecha hará que cualquier componente puro se vuelva a procesar todo el tiempo.
Ejemplo
Tiene un componente principal con un controlador de cambios como:
y con un render como:
{ tasks.map(task => <MyTask handleChange={this.handleChange(task)}/> }
handleChange luego se usa en una entrada o haga clic. Y todo esto funciona y se ve muy bien. PERO significa que cualquier cambio que hará que los padres vuelvan a rendirse (como un cambio de estado completamente no relacionado) también volverá a procesar TODA su MyTask, aunque sean Componentes Puros.
Esto puede aliviarse de muchas maneras, como pasar la flecha 'más externa' y el objeto con el que lo alimentaría o escribir una función de actualización personalizada o volver a lo básico, como escribir funciones con nombre (y vincular esto manualmente ...)
fuente