La explicación es muy simple, funciones que devuelven funciones, pero su potencial se entiende con el concepto de{' '}
currying
HOC?
Las HOC son literalmente funciones que aceptan y devuelven otras funciones
La frase es algo abstracta, pero es literal, y dicho así parece un concepto muy sencillo
Y lo parece porque lo es:
Vamos a suponer que tenemos un array al que queremos sumarle los valores de otro array
const arr = [5, 6, 7]
const changes = [1, 1, 1]
const new_arr = arr.map((el, i) => el + changes[i])
console.log(new_arr) // [6,7,8]
Bien, pues vamos a refactorizarlo con una función que se encargue de esto mismo
const sum_arrays = (arr1, arr2) => arr1.map((el, i) => el + arr2[i])
const arr = [5, 6, 7]
const changes = [1, 1, 1]
const new_arr = sum_arrays(arr, changes)
console.log(new_arr) // [6,7,8]
La función sum_arrays
técnicamente ya es una HOC ya que es una función que nos devuelve un map
, que es otra función
Pero además es que map()
es otra HOC ya que nos devuelve otra función
En realidad estamos escribiendo con HOCs todo el rato, entonces a qué viene tanto misterio?
Currying
Bien, pues ahora vamos a volver a refactorizar el código anterior, pero en este caso lo hacemos porque queremos atomizar la función, no nos gusta que sum_arrays
tenga que recibir 2 argumentos, queremos que reciba sólo uno
El razonamiento es porque así vamos a poder reutilizar la función de forma mucho más fácil
const sum_arrays = arr1 => arr2 => arr1.map((el, i) => el + arr2[i])
const arr = [5, 6, 7]
const changes = [1, 1, 1]
const new_arr = sum_arrays(arr)(changes)
console.log(new_arr) // [6,7,8]
Bien, ya tenemos nuestra función atomizada y el resultado es exactamente el mismo
La pregunta parece obvia: De qué nos sirve expresar sum_arrays
de este modo?
Pues porque nos da mucha versatilidad
Lo puedes ver en el siguiente ejemplo donde cambio la función del array por algo distinto como cambiar el estado de un usuario
const user_status = user => new_status => user.status = new_status
const user1 = {name: 'me', status: 'pending'}
const user2 = {name: 'myself', status: 'pending'}
const updateUser1 = user_status(user1)
const updateUser2 = user_status(user2)
updateUser1('valid')
updateUser2('delete')
console.log(user1) // {name: "me", status: "valid"}
console.log(user2) // {name: "myself", status: "delete"}
Es decir, con nuestra función atomizada podemos definir funciones más semánticas como updateUser1
y updateUser2
que se componen de la función más abstracta user_status
, y todo queda más legible y más bonito
A esto se le llama currying
, y lo bueno de las HOCs es que precisamente son las que permiten escribir en currying
🙋♂️
Lista de correo: escribo algo de tanto en cuanto