DEV Community

Heiker
Heiker

Posted on Edited on Originally published at vonheikemen.github.io

La utilidad de los reducers

En un artículo anterior les hablÃĐ del mÃĐtodo .reduce, cÃģmo funciona y el caso ideal en el que podemos usarlo (en mi opinion). Esta vez voy a mostrar mÃĄs casos en los que podría ser una buena opciÃģn. Ahora bien, no tienen que haber leído ese artículo pero de aquí en adelante voy a asumir que saben cÃģmo funciona el mÃĐtodo Array.reduce. Al finalizar espero que aprendan a reconocer en quÃĐ lugares .reduce podría funcionar perfectamente.

ÂŋQuÃĐ estamos buscando?

Patrones, buscamos patrones. Bueno... sÃģlo uno. Y para saber quÃĐ estamos buscando tenemos que ver los requerimientos de un reducer. Piensen en ellos por un momento, cuando empiezan a escribir uno que quieren usar con Array.reduce tal vez luce así.

function (accumulator, value) {
  /*
    algo de lÃģgica por aquí
  */
  return accumulator;
}
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Okey, por lo general retornamos una copia modificada de accumulator pero eso no es importante, el punto es que retornamos el mismo "tipo" de dato que obtuvimos en el primer parÃĄmetro. Entonces tenemos que la comportamiento de la funciÃģn es el siguiente.

(Accumulator, Value) -> Accumulator
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Pero en este caso lo que tenemos aquí es un ejemplo concreto. Yo quiero que vean esto de una forma mÃĄs abstracta. Lo que en realidad buscamos son funciones con esta forma.

(A, B) -> A
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Eso es bÃĄsicamente todo lo que necesitan saber. Para que un reduce pueda hacer bien su trabajo sÃģlo debe ser capaz de retornar el mismo tipo de dato que recibiÃģ en el primer parÃĄmetro.

ÂŋAÚn estÃĄn confundidos? No se preocupen, pasaremos lo que queda de este artículo revisando ejemplos donde este patrÃģn puede aparecer.

Casos de uso

Acumuladores

Aquí generalmente es la parte donde les muestro una situaciÃģn donde sumamos un arreglo de nÚmeros o algo parecido. No hagamos eso. Podemos imaginarnos un escenario mÃĄs complejo donde un acumulador nos sea Útil.

Entonces, vamos a fingir que estamos trabajando en un proyecto que tiene una especie de blog y nos encontramos creando la pÃĄgina del perfil de usuario. Queremos mostrar todos los tags donde el usuario tiene por lo menos un artículo. QuizÃĄ quieran extraer ese dato de la base de datos usando una consulta elaborada pero eso llevaría mucho tiempo. Primero hagamos un prototipo.

Antes de hacer las cosas de la manera adecuada lo que vamos a hacer es transformar un arreglo que contiene todos los artículos en un Set con todos los tags, para eso usaremos Array.reduce.

// Imaginen que estos objetos son mÃĄs complejos
const posts = [
  { tags: ["javascript", "discuss"] },
  { tags: ["javascript", "react", "vue-is-better"] },
  { tags: ["discuss"] },
  { tags: ["javascript"] },
];

function dangerously_add_tags(acc, post) {
  for(let value of post.tags) {
    acc.add(value);
  }

  return acc;
}

posts.reduce(dangerously_add_tags, new Set());
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Este sería el resultado.

Set(4) [ "javascript", "discuss", "react", "vue-is-better" ]
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Ahora piensen en el comportamiento de nuestro reducer. Tenemos un Set con tags que hace el papel de Accumulator y un objeto que representa un post como nuestro Value. Podríamos decir que se comporta de la siguiente manera.

(Set, Objeto) -> Set
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Bueno, tÃĐcnicamente Objeto no puede ser cualquier objeto, debe tener una propiedad llamada tags. Así que sería algo mÃĄs como esto.

(Set, Artículo) -> Set
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

En fin, este es el patrÃģn del que les hablaba (A, B) -> A. La implementaciÃģn de dangerously_add_tags demanda que B sea un Artículo. Pero para que esta funciÃģn sea un reducer debe ser capaz de retornar el mismo tipo de dato que recibiÃģ en el primer parÃĄmetro (Set), y eso lo logramos retornando acc.

Transformaciones

Probablemente han escuchado que pueden usar Array.reduce para suplantar otros mÃĐtodos del prototipo Array, pero aunque esto suene como un dato interesante no tiene mucha utilidad. ÂŋPor quÃĐ harían algo así? No tiene sentido para mí. Sin embargo, aÚn puede resultar Útil si planean "fusionar" las características de varios de esos mÃĐtodos en uno. ÂŋAlguna vez han querido filtrar y transformar un arreglo al mismo tiempo? Con .reduce eso es posible.

Vamos a reusar nuestra variable posts aquí tambiÃĐn.

const posts = [
  {
    category: "javascript",
    tags: ["javascript", "discuss"]
  },
  {
    category: "frameworks",
    tags: ["javascript", "react", "vue-is-better"]
  },
  {
    category: "watercooler",
    tags: ["discuss"]
  },
  {
    category: "functional programming",
    tags: ["javascript"]
  },
];
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Esta vez lo que queremos hacer es filtrar los que tengan el tag discuss, y por cada uno que pase la prueba queremos extraer la categoría y capitalizar el valor. ÂŋCÃģmo haríamos eso?

function capitalize(str) {
  return str[0].toUpperCase() + str.slice(1);
}

function filter_map_posts(acc, post) {
  // aquí estamos filtrando
  if(post.tags.includes('discuss')) {
    return acc.concat(
      // esta es la transformaciÃģn
      capitalize(post.category)
    );
  }

  return acc;
}

posts.reduce(filter_map_posts, []);
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Aquí tenemos nuestro resultado.

Array [ "Javascript", "Watercooler" ]
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

ÂŋPor quÃĐ funciona? Si revisan el comportamiento de filter_map_posts tenemos esto.

(Arreglo, Artículo) -> Arreglo
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

CoordinaciÃģn

Si han indagado un poco en librerías enfocadas en el paradigma funcional hay una alta probabilidad de que se hayan topado con una funciÃģn llamada pipe. Con esta funciÃģn podemos combinar una cantidad arbitraria de funciones. Esta es la manera en la que se usa.

pipe(
  una_funcion,
  otra,
  proceso_serio,
  efectos_adelante,
);
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

La idea detrÃĄs de esto se centra en transportar el resultado de una funciÃģn hacia la siguiente en la lista. En efecto lo que hacemos aquí es coordinar llamadas de funciones. En este caso, el fragmento anterior es equivalente a esto:

function pipe(arg) {
  return efectos_adelante(proceso_serio(otra(una_funcion(arg))));
}
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Si se preguntan por quÃĐ les digo esto, es porque podemos implementar pipe usando .reduce. Si se fijan bien notarÃĄn que lo Único que hacemos en esa funciÃģn es aplicar funciones a un argumento. Eso es todo. No hay nada mÃĄs.

ÂŋY quÃĐ?

ÂĄEs una operaciÃģn binaria! Podemos transformar eso en una funciÃģn.

function apply(arg, fn) {
  return fn(arg);
}
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

ÂŋY saben quÃĐ funciona bien con operaciones binarias? Nuestro amigo .reduce.

function pipe(...fns) {
  return function(some_arg) {
    return fns.reduce(apply, some_arg);
  };
}
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Lo primero que hacemos en pipe es recolectar la lista de funciones que usaremos y convertirla en un arreglo. El segundo paso es retornar una funciÃģn que desencadenarÃĄ las llamadas a las funciones en nuestro arreglo, tambiÃĐn en este paso obtenemos nuestro argumento inicial. Al final de eso, con todo en su lugar, .reduce se encarga del resto. Pueden probarlo ustedes mismos.

const post = { 
  category: "javascript",
  tags: ["javascript", "discuss"] 
}

function capitalize(str) {
  return str[0].toUpperCase() + str.slice(1);
}

function get_prop(key) {
  return function(obj) {
    return obj[key];
  }
}

function exclaim(str) {
  return str + "!!";
}

const exciting_category = pipe(
  get_prop("category"),
  capitalize,
  exclaim
);

exciting_category(post);
// => Javascript!!
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Okey, okey. Ahora bien, ÂŋCÃģmo es que apply sigue el patrÃģn?

Ah, buena pregunta. Es algo raro pero aÚn podemos darle sentido. Mírenlo de esta manera.

(Algo, FunciÃģn) -> Algo
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Si tienen una unidad de lo que sea (literalmente cualquier cosa) y una funciÃģn, apply harÃĄ su trabajo. Pero tengan presente que aquí no hay garantía de que su funciÃģn no explote, esa sería responsabilidad de ustedes.

Cambios de estado a travÃĐs del tiempo

Este bonus track es para todos aquellos desarrolladores frontend allí afuera.

Si han pasado cualquier cantidad de tiempo investigando sobre librerías para manejar el estado de una aplicaciÃģn tal vez hayan escuchado de una cosa llamada redux. Esta librería tiene un enfoque interesante porque espera que el usuario (el desarrollador) suministre un reducer que sea capaz de manejar los cambios en el estado de la aplicaciÃģn. A algunos les parece genial, a otros no. Pero bien sea que estÃĐn de acuerdo con esto o no, su enfoque tiene mucho sentido. DÃĐjenme mostrarles.

Empecemos con el reducer. En esta ocasiÃģn necesitamos uno con este comportamiento.

(Estado, AcciÃģn) -> Estado
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Estado y AcciÃģn son objetos. Aquí no hay nada extravagante. La "forma" de nuestro Estado depende de la aplicaciÃģn en la que trabajamos, los desarrolladores pueden hacer lo que quieran con ÃĐl. La AcciÃģn por otro lado debe tener una propiedad type, y redux se asegura de esto.

Entonces, vamos a fingir que este es el estado de una aplicaciÃģn imaginaria en la que estamos trabajando.

const state = {
  count: 40,
  flag: false
};
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Ah, sí. Un milagro de la ingeniería.

Ahora que sabemos cÃģmo luce el Estado, y tambiÃĐn sabemos quÃĐ necesita una AcciÃģn, podemos comenzar a escribir nuestro reducer.

function reducer(state, action) {
  switch(action.type) {
    case 'add':
      return {
        ...state,
        count: state.count + 1,
      };
    case 'subtract':
      return {
        ...state,
        count: state.count - 1,
      };
    case 'toggle_flag':
      return {
        ...state,
        flag: !state.flag,
      };
    default:
      return state;
  }
}
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Aquí viene la parte curiosa: no necesitamos redux para probar nuestro reducer. Es un reducer genÃĐrico, bien podríamos usarlo con Array.reduce para ver quÃĐ puede hacer.

const actions = [
  { type: 'add' },
  { type: 'add' },
  { type: 'subtract' },
  { type: 'add' },
  { type: 'subtract' },
  { type: 'add' },
  { type: 'toggle_flag' }
];

actions.reduce(reducer, state);
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

actions.reduce debería devolvernos otra "instancia" de nuestro estado. En nuestro caso, despuÃĐs de aplicar todas esas acciones, tendríamos el siguiente resultado.

{
  count: 42,
  flag: true
}
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Y allí lo tienen, la funcionalidad principal de redux sin redux.

Vamos a dar un paso adelante en nuestro proceso e introduzcamos el concepto de tiempo. Para esto vamos a agregar una tienda "falsa" de redux. Bueno... la tienda serÃĄ "real" pero serÃĄ una imitaciÃģn barata. Empecemos.

function Store(reducer, state) {
  let _listener = null;

  const get_state = function() {
    return state;
  };

  const subscribe = function(listener) {
    _listener = listener;
  };

  const dispatch = function(action) {
    state = reducer(state, action);
    _listener && _listener();

    return action;
  };

  return { get_state, dispatch, subscribe };
}
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

ÂŋTodo bien? ÂŋSaben lo que ocurre ahí? La parte que realmente nos interesa es la del dispatch. Esto de aquí.

const dispatch = function(action) {
  state = reducer(state, action);
  _listener && _listener();

  return action;
};
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Esta funciÃģn se encarga de reemplazar el Estado actual. Como mencionÃĐ antes, el reducer se encarga de la lÃģgica que dice cÃģmo actualizar el Estado. La tienda (Store) se encarga de la lÃģgica que dice cuando debe actualizarse. Suficiente palabrería, vamos a probarlo.

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

const store = Store(reducer, state);
store.subscribe(function() {
  console.log(store.get_state());
});

(async function() {
  store.dispatch({ type: 'add' });
  await delay(500);

  store.dispatch({ type: 'add' });
  await delay(500);

  store.dispatch({ type: 'subtract' });
  await delay(700);

  store.dispatch({ type: 'add' });
  await delay(400);

  store.dispatch({ type: 'subtract' });
  await delay(800);

  store.dispatch({ type: 'add' });
  await delay(100);

  store.dispatch({ type: 'toggle_flag' });
})();
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Si ejecutan eso notarÃĄn cÃģmo los mensajes aparecen en pantalla (o la cÃģnsola del navegador) con una pequeÃąa demora entre cada uno.

- { count: 41, flag: false }
- { count: 42, flag: false }
- { count: 41, flag: false }
- { count: 42, flag: false }
- { count: 41, flag: false }
- { count: 42, flag: false }
- { count: 42, flag: true }
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

ÂŋSe dieron cuenta que el resultado final es el mismo que nos dio Array.reduce? ÂŋNo es genial?

Si quieren jugar con el verdadero redux aquí les dejo un ejemplo en codepen.

ConclusiÃģn

Espero que en este punto los reducers no parezcan tan misteriosos y aterradores. SÃģlo recuerden que se trata de una funciÃģn con este comportamiento.

(A, B) -> A
ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™

Eso es todo. No hay ninguna magia extraÃąa detrÃĄs de eso. Si pueden hacer que una funciÃģn tenga esas características pueden estar seguros que funcionarÃĄ de maravilla con cualquier cosa que actue como .reduce.

Fuentes


Gracias por su tiempo. Si este artículo les pareciÃģ Útil y quieren apoyar mis esfuerzos para crear mÃĄs contenido pueden dejar una propina en ko-fi.com/vonheikemen.

buy me a coffee

Top comments (4)

ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™
 
juanfrank77 profile image
Juan F Gonzalez •

Que interesante esto sobre funcionalidad de Redux sin Redux. Este mÃĐtodo reduce me cae bien no sÃģlo por ser bien Útil sino porque recuerda la funcionalidad de los "folds" en Haskell y Functional Programming FTW!

ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™
 
vonheikemen profile image
Heiker •

Que interesante esto sobre funcionalidad de Redux sin Redux.

Era un dato curioso que siempre quise mencionar. Ahora que en react tiene un hook llamado useReducer ese dato puede resultar Útil incluso si la gente ya no usa redux.

recuerda la funcionalidad de los "folds" en Haskell y Functional Programming FTW!

No sÃĐ mucho de haskell pero segÚn la especificaciÃģn Fantasy Land, definitivamente hay una relaciÃģn.

ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™
 
juanfrank77 profile image
Juan F Gonzalez •

Nunca había visto eso de Fantasy Land aunque se ve cool. Pero si reduce en JS es bÃĄsicamente un foldl en Haskell osea coger un arreglo y "doblarlo" de izquierda a derecha.
TambiÃĐn estÃĄ foldr que hace lo mismo pero al revÃĐs.

ðŸ“Ē āđāļˆāđ‰āļ‡āđ€āļ•āļ·āļ­āļ™: vonheikemen/la utilidad de los reducers apa - āļ›āļĢāļ°āđ€āļ”āđ‡āļ™āļĢāđ‰āļ­āļ™ Thread
 
vonheikemen profile image
Heiker •

TambiÃĐn existe el mÃĐtodo .reduceRight en los arreglos.