¿Cómo utilizar el Hook useReducer en React.js?

Inicioreact jsHook 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.

© 2024 EWebik