No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Convierte tus certificados en títulos universitarios en USA

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

19 Días
6 Hrs
54 Min
8 Seg

Middlewares

11/22
Recursos

Aportes 36

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Este es el middleware que se me ocurrió: Agregar el prefijo “Poke :” al nombre de cada pokemon.

export const prefix = store => next => action => {
    const prefixed = action.action.payload.map( pokemon => ({
        ...pokemon,
        name: 'Poke: ' + pokemon.name
    }) )

    const updatedAction = {
        ...action,
        action: {...action.action, payload: prefixed}
    }
    next(updatedAction);
}

Creo que ha esto se refería la profesora cuando menciona que la curva de aprendizaje es más pronunciada en Redux comparada a Context API. La sintaxis del middleware me parece bien complicada: una función que recibe como argumento otra función la cual a su vez devuelve otra función… y creo que allí termina. Seguro que la puedo memorizar pero me interesa más entenderla. ¿Sería equivalente a escribir lo siguiente?:


export const logger = function(store) {
	return function(next) {
		return function(action) {
  			console.log(action);
  			next(action);
		};
	};
};

Para los que no entendieron el concepto de Currying functions aquí un artículo, obviamente en inglés como lo está el 99.999% de la información en internet:

https://javascript.info/currying-partials

Middlewares:
Es una pieza de código que se ejecuta cuando X recibe un request y ese mismo X da respuesta al request.

Ayuda a los desarrolladores a diseñar aplicaciones con mayor eficiencia. Además, actúa como hilo conductor entre las aplicaciones, los datos y los usuarios.

Los podemos usar para:

  • Hacer logs de errores

  • Hacer fetch de data

  • Depurar nuestra aplicación

  • También podemos customizar nuestra data con applyMiddleware

Mi middleware personalizado fue agregarle un numero indexado a cada pokemon. Aqui el codigo

export const number = (store) => (next) => (action) => {
    let arrayPokeWithNumber = [...action.action.payload] 
    for (let i = 0 ; i < arrayPokeWithNumber.length; i++) {
        arrayPokeWithNumber[i].name = `${[i]} - ${arrayPokeWithNumber[i].name}` 
    }
    const newFeature = {
        ...action,
        action:{...action.action, payload: arrayPokeWithNumber}
    }
    next(newFeature)
}

Para quién venga con TS, le dejo el código que a mí me ha funcionado. Reconozco que ha faltado tipar algunas cosas, pero es porque lo estoy practicando.
.
En este caso, me cost;o entender que lo que aparece en el video, no es lo mismo a la respuesta que me estaba dando en consola cuando se mostraba información en el logger. Acá dejo el resultado:

// ** index.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { pokemonsReducer } from './reducers/pokemons';
import { Provider } from 'react-redux';
import { applyMiddleware, compose, legacy_createStore as createStore } from 'redux';
import { featuring, logger } from './middlewares';
import './index.css';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);

const composedEnhancers = compose(
  applyMiddleware(logger, featuring),
  (window as any).__REDUX_DEVTOOLS_EXTENSION__ && (window as any).__REDUX_DEVTOOLS_EXTENSION__(),
)

const store = createStore(pokemonsReducer, composedEnhancers);

root.render(
  <Provider store={store}>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </Provider>
);

.

// ** Middlewares/index.ts

export const logger = (store: any) => {   // store de la aplicación
  return (next: any) => {          // next es una función que se llama cuando el middleware termina su trabajo y envía el action al reducer
    return (action: any) => {      // action es la información que se pasa al reducer
      console.log(action);
      next(action); // <-- hace que el action llegue al reducer
    } 
  }
};

export const featuring = (store: any) => {
  return (next: any) => {
    return (actionNew: any) => {
      debugger;
      const featured = [
        { name: 'Momea', url: 'https://ab.c' }, // <-- nuevo pokemon que quiero meter al state
        ...actionNew.payload, // <-- desestructura todos los pokemons que están en el payload de 'action'
      ];
      const updatedAction = {
        ...actionNew,
        payload: [
          ...featured,
        ]
      }
      next(updatedAction);
    } 
  }
};

No tengo el mismo objeto, por eso en el middleware cambié la forma de desestructurar todo el array

Middleware para invertir el nombre de los pokemones 😃

export const reversed = (store) => (next) => (action) => {
    const reversedPkm = action.action.payload.map((item) => {
        const split = item.name.split('');
        const reverseArray = split.reverse();
        const joinArray = reverseArray.join('');

        return { ...item, name: joinArray };
    });

    const updated = { ...action, action: { ...action.action, payload: reversedPkm } };

    next(updated);
};

la funcionalidad de mi middleware personalizado fue ordenar el arreglo de pokemones en orden alfabético a partir de la propiedad name de cada uno

export const myMiddleware = (store) => (next) => (actionInfo) => {
    const alphabetPokemon = actionInfo.action.payload.map(poke => poke.name).sort()
    const pokemonPayload = actionInfo.action.payload.map((poke, index) => ({ ...poke, name: alphabetPokemon[index] }))

    const myFormatPokemon = {
        ...actionInfo,
        action: { ...actionInfo.action, payload: pokemonPayload}       
    }

    // console.log(myFormatPokemon)
    next(myFormatPokemon)
}

Agregue una nueva propiedad dentro del arreglo de pokemons con el numero del pokemon con el formato #001

export const enumerated = (store) => (next) => (action) => {
    const list = [ ...action.action.payload];    
    const listUpdated = [];
    let count = 0;    
    list.forEach( (pokemon) => listUpdated.push({...pokemon, number: "#" + (++count).toString().padStart(3,'0') }));
    const updatedAction = {...action, action: {...action.action, payload: listUpdated}}
    next(updatedAction);
};

Si están trabajando con ts, encontré esta solución y, hasta el momento parece funcionar
https://www.npmjs.com/package/redux-devtools-extension

Hice un middleware que pone la primera letra del nombre del Pokémon en mayúscula.

export const nameUpperCase = (store) => (next) => (actionInfo) => {

    const featured = [
         ...actionInfo.action.payload.map(
            pokemon => ({
                ...pokemon,
                 name: pokemon.name.charAt(0).toUpperCase() + 
                        pokemon.name.slice(1)
            })
        )
    ]

    const updateActionInfo = {
        ...actionInfo,
        action: {
            ...actionInfo.action,
            payload: featured
        }
    }
    next(updateActionInfo)
}
![](https://static.platzi.com/media/user_upload/image-2fe84156-1c19-40dc-bbe5-7b3a4565093d.jpg) web ![](https://static.platzi.com/media/user_upload/image-9e73a91c-fed3-4ce3-8ef6-7bd4532d2f70.jpg)
Mi middleware es solo agregarle el número en el nombre `export const numbersItems = (store) => (next) => (actionInfo) => {  const myarr = actionInfo.action.payload;  var num = 1;` `  myarr.forEach(element => {    element.name = num +' '+ element.name;     num++;  });` `  const updatedActionInfo = {    ...actionInfo,    action: { ...actionInfo.action, payload: myarr },  };  next(updatedActionInfo);};`
Mi middleware regresa si pikachu existe o no en la respuesta de la api `export const isPikachu = (store) => (next) => (actionInfo) =>{    const fetchedInfo = actionInfo.action.payload;    let pikachu = false;    fetchedInfo.map((item)=>{        let name = item.name        if(name=='pikachu') {            pikachu=true        return 0}    })    console.log('pikachu state: ' + pikachu?'exists':'not exists')    next(actionInfo)}`
Agregue el numero de pokemon del arreglo y lo concatene alnombre ![](https://static.platzi.com/media/user_upload/image-acb64d4f-3a44-4bfe-afc6-d0bc1ed121a9.jpg)
Creo que me adelanté, pero hice un middleware para generar la url del logo de cada Pokémon. ```js export const getUrlLogo = (store) => (next) => (action) => { const getId = (url) => { if(typeof url === 'undefined') return 0; // Para el que nosotros agregamos o si viene vacío. const parts = url.split('/'); const lastPart = parts.pop() || parts.pop(); return lastPart; }; const pokeList = action.action.payload.map( pokemon => ({ ...pokemon, url_image: "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/"+getId(pokemon.url)+".png", })); const updatedAction = { ...action, action: { ...action.action, payload: pokeList} }; return next(updatedAction); }; ```![](https://static.platzi.com/media/user_upload/image-d038442d-c6ec-4915-a6d0-90089485f6f1.jpg)
### Glosario #### Store Creator Es una función que crea el store de redux. #### Enhancer Potenciadores del store. Son funciones de orden superior que toma un store creator y devuelve una versión potenciada. Similar a los middlewares ya que te permite alterar la interfaz del store de manera combinable, por ejemplo los dev tools es un potenciador del store. #### Compose Es una herramienta de programación funcional que combina funciones de derecha a izquierda y lo usamos para poder tener mutiples potenciadores del store.

Mi middleWare que pone la primera letra del pokemon en mayuscula

export const capitalizePokemons = (store)=>(next)=>(action)=>{
    const capitalize = (string) => {
        return string.charAt(0).toUpperCase() + string.slice(1);
    }
    
    const capitalizedPokemons = action.action.payload.map((pokemon) => {
        return {
            ...pokemon,
            name: capitalize(pokemon.name),
        };
    });
    const updatedActionInfo = {
        ...action,
        action: {
            ...action.action,
            payload: capitalizedPokemons
        }
    }
    return next(updatedActionInfo)
}
Hola este es mi middleware transformar los nombres a mayúsculas aunque que ahora que lo pienso es mejor hacerlo con CSS xd. ```js export const capitalize = () => (next) => (actionInfo) => { const capitalize = actionInfo.action.payload.map((pokemon) => ({ ...pokemon, name: pokemon.name.toUpperCase(), })); const updateActionInfo = modifyPayload(actionInfo, capitalize); next(updateActionInfo); }; ```

Aca mi middleware que ordena por nombre descendente usando typescript y chatgpt:

type Order = 'ASC' | 'DES';

export function orderByParam<T>(list: T[], param: keyof T, order: Order = 'ASC'): T[] {
  const multiplier = order === 'ASC' ? 1 : -1;

  return list.sort((a: T, b: T) => {
    const valueA = a[param];
    const valueB = b[param];

    if (valueA < valueB) {
      return -1 * multiplier;
    } else if (valueA > valueB) {
      return 1 * multiplier;
    } else {
      return 0;
    }
  });
}
import { Middleware } from 'redux';
import { orderByParam } from '../utils/strings';
import { Pokemon } from '../actions/types';

export const orderByNameDesc: Middleware = (store) => (next) => (action) => {
  const {action: oldAction} = action;
  const orderList = orderByParam<Pokemon>(oldAction.payload, 'name', 'DES')
  const updatedActionInfo = {
    ...action,
    action: { ...oldAction, payload: orderList },
  };
  next(updatedActionInfo);
};

Proyectos:
Medianos: si quieres usa redux
Pequeño a mediano: Zustand
Mediano a grande: Relay, ReactQuery, React Apollo, SWR

Que sintaxis tan backend-like

MI middleware que agrega un valor aleatorio de poder para cada pokemon

export const addPower = (store: any) => (next: any) => (actionInfo: any) => {

  const featured = actionInfo.payload.map((e: any) => ({ ...e, "power": Math.floor(Math.random() * 100) + 1 }))
  const updatedAction = {
    ...actionInfo, payload: featured
  }
  next(updatedAction)
}

mi middleware

Reto del Middleware:

Poner los nombres de los pokemos en mayúscula:

¡Y este fue el resultado! 🎉

El compañero @CésarPalma dejó el siguiente comentario que me pareció perfecto para entender un poco mejor…

En programación funcional, a esto se le llama hacer currying.
https://yeisondaza.com/currying-en-javascript-funciones-con-superpoderes

Agregar la imagen del pokemon:

export const addImageToPokemons = (store) => (next) => async (action) => {
    let pokemons = action.action.payload

    for (let i = 0; i < pokemons.length; i++) {
        const element = pokemons[i];
        let data = await getImagePokemon(element.name)
        let image = data.data.sprites.front_default

        element.image = image
    }

    next(action)
}

¿Esto esta bien implementado? Porque no necesito pasar la copia del estado 😕

Me esta gustando mucho este curso. La profesora se deja entender muy bien.

Hice un middleware que elimina un pokemon random de todos los que están disponibles, deje console.log para que puedan ver cuál fue el seleccionado y como quedan los pokemons sin ese, aqui esta el middleware ==>

export const removeAnyPokemon = (_store) => (next) => (action) => {
    if (action.action.payload.length === 0) {
        return next(action);
    };

    const numberIdToDelete = Math.floor(Math.random() * action.action.payload.length);
    const pokemonToEliminate = action.action.payload[numberIdToDelete];

    console.log('Selected Pokemon Number and this Pokemon', numberIdToDelete, pokemonToEliminate);
    console.log('Array and its length before removing', action.action.payload, action.action.payload.length);
    
    action.action.payload.splice(numberIdToDelete, 1);
    
    console.log('Array after deletion and its length',action.action.payload, action.action.payload.length);
    
    next(action);
};

Con Redux Toolkit es 1000 veces más sencillo implementar todos estas funciones. Entiendo que es bueno conocer la forma vieja de hacerlo, pero la explicación está un poco mareada, es muy fácil perderse.

Este fue mi middleware

import { Middleware, Dispatch, Action } from 'redux';

const logger: Middleware = ({ getState }: any) => (next: Dispatch) => (action: Action) => {
  console.log('will dispatch', action);
  const returnValue = next(action);
  console.log('state after dispatch', getState());
  return returnValue;
};

const modifyName: Middleware = ({ getState }: any) => (next: Dispatch) => (action: {type:string,payload:any}) => {
    const payload = action.payload;
    payload.forEach((element: {name:string,url:string}) => {
        element.name = `Name: ${element.name}`
    });
    const returnValue = next(action);
    return returnValue;
};

const middleware = {logger,modifyName};
export default middleware;

Yo utilicé un Middleware para poner la primera letra de cada nombre en mayúscula.

export const upperCaseFirstLetterName = (store) =>(next) => (actionInfo) => {
    
    const pokemonsUp = actionInfo.payload.map(pokemon=>{
        
        const upperPok = pokemon.name.charAt(0).toUpperCase() + pokemon.name.slice(1)
        return {name: upperPok}
    })

    
    const updatedPayload = {
        ...actionInfo,
        payload: pokemonsUp
    }
    next(updatedPayload)
}

Currying es una técnica de programación funcional que permite transformar una función que toma múltiples argumentos en una secuencia de funciones que toman un solo argumento cada una.

El objetivo de currying es hacer que las funciones sean más reutilizables y componibles, permitiendo a los desarrolladores crear funciones más específicas a partir de funciones más generales.

Mi middleware personalizado para agregarle una propiedad adicional “isActive” a cada pokemon:

export const addActivationProp = (store) => (next) => actionInfo => {
    const newPayload = actionInfo.action.payload.map(pokemon => pokemon.isActive = true);
    const newActionInfo = { ...actionInfo, payload: newPayload};
    next(newActionInfo);
}

El middeware que cree fue pokemonsWithId que agrega el id a los pokemons.

import types from '../actions/types';

const pokemonsWithId = (store) => (next) => (actionInfo) => {
  if (actionInfo.action.type === types.setPokemons) {
    const pokemons = actionInfo.action.payload;
    const pokemonsWithId = pokemons.map((pokemon, i) => ({ ...pokemon, id: i + 1 }));
    
    const updatedAction = {
      ...actionInfo,
      action: { ...actionInfo.action, payload: pokemonsWithId },
    };
    next(updatedAction);
  } else {
    next(actionInfo);
  }
};

export default pokemonsWithId;

Para usar los devtools y el middleware lo hice de la siguiente manera, use un paquete

npm install --save-dev redux-devtools-extension

import { composeWithDevTools } from "redux-devtools-extension";

const middlewareEnhancer = applyMiddleware(logger);

const store = createStore(
  pokemonsReducer,
  composeWithDevTools(middlewareEnhancer)
);

funciona perfecto por si alguno tiene un error y está usando TypeScript