¬ŅC√≥mo utilizar el Hook useReducer en React.js?

Inicio‚Äļreact js‚ÄļHook useReducer
¬ŅC√≥mo utilizar el Hook useReducer en React.js?

by Juan Carlos García

7-My-2023

(10)

Suscribirme al canal:

Hola viajero, hemos avanzado muy bien en este curso de React JS, hoy toca hablar del Hook useReducer, el cual, estoy seguro te ser√° muy √ļtil en tus proyectos, como siempre veremos su declaraci√≥n, definici√≥n y mucho m√°s, espero te guste este post.

Si te esta gustando este curso, puedes ayudarme compartiendo este post, suscribiéndote a mi boletín y a mi canal.

¬°No te puedes perder las nuevas clases ūüßź!

React JS

React JS

React.js: El mejor curso gratuito de React.js desde cero.

¬ŅQue es React JSX?

¬ŅQue es React JSX?

Gu√≠a para principiantes de React JSX: ¬ŅQu√© es React JSX? Introducci√≥n a React JSX

Componentes y propiedades

Componentes y propiedades

Components and Props React.js, Manejo de propiedades y componentes en React

State y Ciclo de vida en React

State y Ciclo de vida en React

State And Lifecycle: Comprendiendo el State y Ciclo de vida de los componentes en React.js

Refs React

Refs React

¬ŅQu√© son las React Refs y para que sirven? Uso de las Refs y manejo del DOM en React.js

Listas y condiciones en React

Listas y condiciones en React

Keys and List: ¬ŅC√≥mo manejar las listas y condicionales en React JS?

Formularios en React

Formularios en React

Formularios en React: ¬ŅC√≥mo manejar los formularios en React.js con input controlados y no controlados?

React develepor tools

React develepor tools

React Developer Tools: ¬ŅC√≥mo analizar el comportamiento y estado de nuestros componentes en React.js?

API Context

API Context

API Context en React: ¬ŅC√≥mo comunicar componentes mediante API Context en React.js?

Higher Order Component

Higher Order Component

HOC en React.js: ¬ŅC√≥mo utilizar los High Order Component (HOC) ?

Children en React JS

Children en React JS

Children en React.js: Manejo avanzado de Children en React.js, composición de componentes.

PropTypes en React

PropTypes en React

PropType en React.js: ¬ŅC√≥mo validar datos a trav√©s de PropType en React.js?

Hooks en React JS

Hooks en React JS

Master de Hooks en React JS: ¬ŅQu√© es un Hook en React.js? Tipos, funcionamiento y caracter√≠sticas.

Hook useState

Hook useState

useState: ¬ŅC√≥mo utilizar el Hook useState en React.js?

Hook useEffect

Hook useEffect

Hook useEffect: ¬ŅQu√© es el Hook useEffect? ¬ŅC√≥mo utilizarlo correctamente y qu√© reglas seguir?

Hook useContext

Hook useContext

¬ŅC√≥mo utilizar el Hook useContext? Comunicaci√≥n de componentes funcionales

Hook useReducer

Hook useReducer

¬ŅC√≥mo utilizar el Hook useReducer en React.js?

React memo

React memo

Memorizar componentes a través de React.memo en React.js

Hook useCallback

Hook useCallback

Utilizando los Hooks useCallback y useMemo en React.js

ūüßź Autoevaluaci√≥n: Hook useReducer

¬ŅQu√© es y para qu√© sirve useReducer?

¬ŅCu√°ndo usar el Hook useReducer?

¬ŅQu√© aprender√°s de useReducer?

  • C√≥mo declararlo.
  • La forma correcta en que debes inicializar tu state.
  • Aprender√°s a crear tu funci√≥n reducer.
  • Haremos un ejemplo donde mediante un clic incrementaremos o disminuiremos el valor de un contador.

Repositorio

  • Puedes descargar el c√≥digo dando clic aqu√≠.
  • O puedes clonar el repositorio y cambiarte a la rama "usereducer".
git clone https://github.com/EWebik/react-js.git
git checkout usereducer

 

¬ŅQu√© es y para qu√© sirve el Hook useReducer?

El useReducer es un Hook que nos permite manipular el state de nuestros componentes funcionales, esto se logra a través de:

  • Una funci√≥n reducer
  • Y un funci√≥n de retorno llamada dispatch con la cual podemos combinar o emparejar el state.

UseReducer esta basado en la librería Redux, es por ello que, aparecen las palabras, reducer y dispatch.

 

¬ŅCu√°ndo usar el Hook useReducer?

Bien, esto no será una respuesta como tal, ya que, depende del tipo de proyecto, pero, se pueden tomar como recomendaciones para tomar una decisión:

  • Cuando el estado siguiente del "state" depende del estado anterior.
  • Cuando manejas un objeto JSON como state y tienes subvalores dentro de tu mismo objeto.
  • Cuando la l√≥gica es muy compleja.

 

 Declaraci√≥n de useReducer

En forma general podemos declarar a este Hook de la siguiente forma.

const [state, dispatch] = useReducer(reducer, initialArg, init);

No obstante, la declaración también depende de como decidamos iniciar el state:

  • Podemos especificar el estado inicial.
  • O podemos especificar un estado inicial en forma diferida.

 

Especificando el estado inicial de useReducer

La forma más sencilla de inicializar el state es, especificar el objeto del state y pasarlo como segundo parámetro al useReducer, tal y como lo hacemos en el vídeo.

const [state, dispatch] = useReducer(reducer,initialState);

 

Inicialización del state en forma diferida

Esto no lo ocupamos en el vídeo, pero, no esta de más que conozcas esta opción. Esta forma hace referencia que, usamos todos los argumentos de useReducer, donde:

  • El primero no cambia, ser√° nuestra funci√≥n reducer.
  • El segundo sigue siendo valores iniciales que tendr√° nuestro state, sin embargo, no ser√° el valor inicial total de nuestro state.
  • El tercer par√°metro es una funci√≥n que recibir√° el objeto del segundo argumento, aqu√≠ construiremos nuestro state final y lo regresaremos.

Creo que debo explicar un poco más ese tercer argumento, simplemente debemos entender que, esta función recibirá como argumento el objeto que se encuentra en el segundo argumento de useReducer, y dentro de esta función, puedes decidir como tomar este dato y agregarlo al state final, esto quiere decir que, puedes tener este objeto más otros datos que requieras agregar al state, por ejemplo:

function init(initState) {
  return {
      ...initState,
      dato:true
  };
}

function Counter({initState}) {
    const [state, dispatch] = useReducer(reducer, initState, init);
   
   ....

}

Si deseas que haga un ejemplo de esto en vídeo, suscríbete a mi canal y déjame un mensaje en los comentarios de este vídeo, si hay muchos comentarios hago un ejemplo de esto.

¬ŅC√≥mo utilizar useReducer?

Bien, espero que en este punto ya hayas visto el vídeo de la clase, donde, hacemos un ejemplo paso a paso y te explico cada parte del código y, obviamente, ya esta el código en el repositorio.

Creo que lo que falta nada m√°s es establecer un par de ventajas y desventajas al utilizar este Hook.

Ventajas

  • Permite actualizar el state a partir de un estado anterior.
  • La l√≥gica de la actualizaci√≥n de subatributos de nuestro state, es m√°s f√°cil de comprender.

Desventajas

  • De entrada, debes escribir mucho m√°s c√≥digo que si utilizar√°s useState.
  • Debes de aprender nuevos conceptos, como lo es el: reducer y dispatch.

 

Excelente, aquí te dejo el resumen del vídeo y el ejemplo que desarrollamos, pero, te recomiendo que cuando tengas tiempo mires el vídeo para que despejes cualquier duda.

 

Ejemplo contador

El ejemplo que vamos hacer es un peque√Īo contador que tiene la capacidad de:

  • Contar√° con un checkbox que indicar√° si la cuenta aumenta o disminuye.
  • UN input text que indicar√° el intervalo de la cuenta
  • Un bot√≥n que aumente la cuenta o la disminuya, seg√ļn el valor del checkbox
  • Otro bot√≥n que realice un reset y regrese al contado a su estado inicial.
Ejemplo del contador utilizando useReducer

Como puedes observar es una interfaz muy simple, pero, ten en cuenta que lo que estamos estudiando es al Hook y no estilos, así que, para fines demostrativos nos sirve perfectamente.

 

State Inicial

Lo primero que vamos hacer es declarar nuestro state inicial, es recomendable que este objeto o JSON, este declarado fuera de tu componente, a menos que venga en las propiedades claro.

//Estado inicial
const initialState = {
  count:0,
  countInterval:1,
  increment:true
}

 

Declaración del reducer

Ahora vamos a crear la función reducer donde actualizaremos el valor del state

//Reducer, el cual debe cumplir con las características de una función pura
const reducer = (state, action)=>{
  switch (action.type) {
    case "INCREMENT":
      return{
        ...state,
        increment: action.increment
      }
    case "SET_INTERVAL":
      return{
        ...state,
        countInterval: parseInt(action.countInterval)
      }
    case "INCREASE_COUNT":
      return{
        ...state,
        count: state.count + state.countInterval
      }
    case "DECREASE_COUNT":
      return{
        ...state,
        count: state.count - state.countInterval
      }
    case "RESTART":
      return initialState;
    default:
      //Lanzar un error
      return state;
  }
}

 

La funci√≥n reducer por lo regular es un swith donde eval√ļas el valor de TYPE, esta funci√≥n debe contar con las caracter√≠sticas de una funci√≥n pura:

  • Una funci√≥n pura en JavaScript se refiere a que dadas ciertas entradas, regresar√° siempre las mismas salidas.
  • Un funci√≥n pura, no afecta ni modifica los atributos de entrada.

 

Declaración de nuestro componente

const Counter = ()=>{
  //Declaración
  //const [state, dispatch] = useReducer(()=>{},{});
  const [state, dispatch] = useReducer(reducer,initialState);

  const handleIncrement = (e)=>{
    const {checked}=e.target;
    dispatch({type:"INCREMENT",increment:checked});
  }
  const handleCountInterval = (e)=>{
    const {value}=e.target;
    dispatch({type:"SET_INTERVAL",countInterval:value});
  }
  const handleCount = (e)=>{
    if(state.increment){
      dispatch({type:"INCREASE_COUNT"});
    }else{
      dispatch({type:"DECREASE_COUNT"});
    }
  }
  const handleRestart = (e)=>{
    dispatch({type:"RESTART"});
  }

  return(
    <div className="padre">
      <h1>{"Hook useReducer by EWebik"}</h1>
      <p>{"Cuenta: " + state.count}</p>
      <div>
        <input
          type="checkbox"
          id="chk"
          checked={state.increment}
          onChange={handleIncrement} />
        <label htmlFor="chk">
          {"Incrementar"}
        </label>
      </div>
      <br/>
      <div>
        <label htmlFor="interval">
          {"Intervalo"}
        </label>
        <input
          type="text"
          id="interval"
          value={state.countInterval}
          onChange={handleCountInterval} />
      </div>
      <br/>
      <button onClick={handleCount}>
        {state.increment ? "Incrementar":"Decrementar"}
      </button>
      <button onClick={handleRestart}>
        {"Reiniciar"}
      </button>
    </div>
  )
}

 

Utilización del dispatch

Como pudiste observar, en los manejadores de eventos utilizamos el dispatch, ya que, a través del llamado de esta función, le pasamos los parámetros a la función reducer para que esta actualice el state.

  • En el dispatch debemos pasar el atributo a evaluar en el swith que en este caso es el TYPE m√°s los dem√°s a tributos que deseamos actualizar en el state, por ejemplo:
const handleIncrement = (e)=>{
    const {checked}=e.target;
    dispatch({type:"INCREMENT",increment:checked});
  }

 

  • No obstante, en el dispatch podemos pasar √ļnicamente el atributo a evaluar (TYPE), por ejemplo:
  const handleCount = (e)=>{
    if(state.increment){
      dispatch({type:"INCREASE_COUNT"});
    }else{
      dispatch({type:"DECREASE_COUNT"});
    }
  }

 

Y listo, ya tenemos nuestro contador funcionando a través de useReducer, si bien, lo pudimos hacer utilizando useState, es un excelente ejemplo de como puedes utilizar cada uno de los argumentos de este Hook.

 

ūüßź Autoevaluaci√≥n: Hook useReducer

¬ŅQu√© es y para qu√© sirve useReducer?

¬ŅCu√°ndo usar el Hook useReducer?

Juan Carlos

Juan Carlos García

Desarrollador de software / SEO

Durante a√Īos he desarrollado plataformas dedicadas al rastreo satelital y varios sitios web que se encuentran en la primera p√°gina de Google, y hoy quiero compartir contigo lo que se en tecnolog√≠as como: Node JS, PHP, C# y Bases de datos.

Si quieres apoyarme sígueme en mis redes sociales y suscríbete a mi canal de YouTube.

EWebik

Dise√Īo de p√°ginas web y aplicaciones moviles.

© 2023 EWebik