react logo

Domina los Hooks de React: Los 7 más importantes que debes conocer

javascriptreacthooks

Tomás Cuevas

/

Introducción

Si estás construyendo aplicaciones en React, los Hooks son el equivalente a tener en tus manos herramientas de construcción de alta calidad. Con ellos, puedes crear aplicaciones duraderas y de alta calidad de manera eficiente y sin esfuerzo. Pero, ¿sabes cuáles son los 7 Hooks más importantes de React?. En este artículo, descubrirás cómo utilizarlos, para qué sirven y por qué deberías incluirlos en tus proyectos. Prepárate para llevar tus habilidades de desarrollo al siguiente nivel.

¿Qué son los Hooks?

Los hooks son una característica de React, que permiten a los desarrolladores utilizar el estado y otras características de React en componentes. Con los hooks, los desarrolladores pueden reutilizar la lógica de estado y efectos secundarios en diferentes componentes, lo que hace que el código sea más fácil de mantener y menos propenso a errores.

En este articulo aprenderas sobre los siguientes hooks:

  • useState: Este hook permite que un componente tenga un estado interno y que se actualice cada vez que se llama a la función setState.
  • useEffect: Este hook se utiliza para manejar los efectos secundarios de un componente, como actualizar el DOM o llamar a una API. Se llama después de que se renderice el componente y puede actualizar el estado o las props.
  • useContext: Este hook permite a un componente acceder a un contexto proporcionado por un componente padre.
  • useReducer: Este hook permite a un componente manejar el estado mediante la implementación de una función reductora que recibe el estado actual, una acción y devuelve un nuevo estado.
  • useRef: Este hook se utiliza para crear una referencia mutable que se puede mantener durante toda la vida útil del componente.
  • useCallback: Este hook permite a un componente crear una función memorizada que puede ser pasada como una prop sin necesidad de volver a renderizar el componente.
  • useMemo: Este hook permite a un componente memorizar el resultado de una función costosa y reutilizarlo en futuras renderizaciones.

useState

El hook useState es probablemente el más utilizado de todos los hooks de React. Permite a los desarrolladores almacenar y actualizar el estado dentro de un componente. En otras palabras, useState permite que los componentes tengan una memoria interna que pueden usar para almacenar y cambiar datos.

¿Comó utilizar useState?

Para utilizar useState, es necesario importarlo desde la biblioteca de React. Luego, se puede llamar dentro de un componente funcional de React y proporcionar un valor inicial para el estado. Este valor inicial puede ser cualquier tipo de dato válido en JavaScript.

useState devuelve un array con dos elementos: el primero es el valor actual del estado y el segundo es una función para actualizar el estado. Esta función suele llamarse 'setNombreDelEstado', comenzando con la palabra set seguida del nombre del estado.

Ejemplo de uso de useState

import { useState } from "react";

const Counter = () => {
  // inicializamos el estado con un valor de 0
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Haz hecho {count} clicks</p>
      <button onClick={() => setCount(count + 1)}>Cliqueame</button>
    </div>
  );
};

En este ejemplo, useState se utiliza para almacenar el estado del contador dentro del componente Counter. El valor inicial de count es 0, y cada vez que el botón se presiona, el estado se actualiza utilizando la función setCount(). En este caso, estamos tomando el valor de count y luego le sumamos 1.

¿Por qué utilizar useState en React?

Deberías incluir useState en tus componentes de React porque es la forma más sencilla y efectiva de agregar y administrar el estado local en un componente funcional.

En resumen, incluir useState en tus componentes te permite agregar y administrar el estado local de una manera fácil y efectiva, lo que te permite construir componentes interactivos y dinámicos en tus aplicaciones de React.

useEffect

El hook useEffect se utiliza para realizar efectos secundarios dentro de un componente. Esto puede incluir la actualización de un componente después de que cambie el estado, la ejecución de una función después de que se monte o desmonte un componente, o la recuperación de datos de una API.

Parametros necesarios en useEffect

Dentro del hook useEffect, es necesario establecer dos parámetros. El primero es una función que contiene el efecto que se va a ejecutar. El segundo es un array de dependencias que determinará cuándo se volverá a ejecutar el efecto.

Cuando alguno de los valores en el array cambie, el efecto se volverá a ejecutar. Si no se especifica el array, el efecto se volverá a ejecutar con cada cambio en el componente. Si se especifica un array vacío, este tan solo se ejecutará la primera vez que el componente se renderice.

Ejemplo de uso de useEffect

import { useEffect, useState } from "react";

const UserList = () => {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    // realizamos petición HTTP dentro del useEffect
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((response) => response.json())
      .then((data) => setUsers(data));
  }, []);

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

En este ejemplo, useEffect se utiliza para recuperar los datos de una API y almacenarlos en el estado creado con useState llamado 'users'. El segundo parámetro de useEffect es un array vacío, lo que significa que la función se ejecutará solo una vez, cuando se monte el componente.

Conclusiones y precauciones a tomar en cuenta sobre el uso de useEffect

En general, useEffect es un hook muy útil que nos permite manejar efectos secundarios en nuestros componentes. Nos permite realizar operaciones de manera segura y efectiva, como realizar solicitudes de red, actualizar el DOM o manejar la lógica de la aplicación.

Es importante tener precauciones al usar useEffect. Debemos asegurarnos de que los efectos secundarios no sean destructivos, depurarlos adecuadamente y considerar el rendimiento al usarlos. Además, debemos tener en cuenta las dependencias y evitar bucles infinitos al actualizar el estado dentro del efecto.

useContext

El hook useContext se utiliza para acceder al contexto dentro de un componente. El contexto es una forma de pasar datos a través de la jerarquía de componentes sin tener que pasar props manualmente en cada nivel.

Crear Context

Para utilizar useContext, primero se debe crear un contexto utilizando el método createContext. Este contexto puede contener cualquier tipo de datos, como un objeto, una cadena de texto, un número, etc.

import { createContext } from "react";

// creamos y exportamos el contexto
export const MyContext = createContext();

Crear Provider

El Provider es un componente que se utiliza para proporcionar datos del contexto a todos los componentes que los necesiten. Este componente envuelve a todos los componentes que necesitan acceder a los datos del contexto.

El Provider recibe la propiedad children, que son los componentes que envolverá y a los que les dará acceso al contexto. Por último, retorna el contexto previamente creado y utiliza la propiedad Provider de ese contexto. Dentro del 'Provider' se coloca el 'children' recibido por props. Además, el 'Provider' recibe una propiedad value, que son los valores que dará acceso a todos los componentes que envuelve.

import { createContext } from "react";

// creamos y exportando el contexto
export const MyContext = createContext();

// componente que exportara el "Provider" del contexto
export const MyContextProvider = ({ children }) => {
  const users = [{ name: "Carlos" }, { name: "Tomás" }, { name: "Juan" }];

  return <MyContext.Provider value={{ users }}>{children}</MyContext.Provider>;
};

Colocar Provider

Es común colocar este Provider en el punto de entrada de nuestra aplicación, envolviendo todos los demás componentes. De esta manera, todos los componentes que formen parte de nuestra aplicación tendrán acceso al contexto proporcionado por el Provider.

import ReactDOM from "react-dom/client";

import { MyContextProvider } from "./context/MyContextProvider"; // provider

import { MyComponent } from "./MyComponent"; // componente hijo
import "./styles.css";

// envolvemos el componente con el provider
ReactDOM.createRoot(document.getElementById("root")).render(
  <MyContextProvider>
    <MyComponent />
  </MyContextProvider>
);

Acceder al contexto mediande useContext

Para acceder a los datos proporcionados por el contexto en un componente específico, debemos utilizar el hook useContext. A continuación, se muestra un ejemplo de cómo se utiliza este hook:

import { useContext } from "react";

// importamos el contexto
import { MyContext } from "./context/MyContext";

export const MyComponent = () => {
  // utilizamos useContext y mandamos como parametro el contexto que queramos usar
  const { users } = useContext(MyContext);

  return (
    <ul>
      {users.map((user) => (
        <li>
          <h3>{user.name}</h3>
        </li>
      ))}
    </ul>
  );
};

En este ejemplo, se utiliza el hook useContext para acceder a los datos proporcionados por el contexto llamado MyContext. En particular, se obtiene el array de objetos 'users' que se encuentra dentro del contexto. Luego, en el componente, se renderiza el nombre de todos los usuarios del array.

useReducer

UseReducer es un hook que se utiliza para manejar el estado de una aplicación en la que los cambios son complejos y requieren una función separada para su actualización. Esta función se llama reducer y se encarga de actualizar el estado de la aplicación en función de la acción realizada en la interfaz de usuario.

Aunque useReducer se utiliza de manera similar a useState, la diferencia principal es que useReducer se basa en el patrón de diseño reducer, comúnmente utilizado en programación funcional.

Sintaxis de useReducer

import { useReducer } from "react";

const [state, dispatch] = useReducer(reducer, initialState);
  • state: Es el estado actual de la aplicación.
  • dispatch: Es una función que se utiliza para actualizar el estado de la aplicación.
  • reducer: Es una función que toma el estado actual, la acción realizada y devuelve un nuevo estado actualizado.
  • initialState: Es el estado inicial de la aplicación.

Función reducer

La función reducer es una parte fundamental del hook useReducer. Esta función recibe dos argumentos: el estado actual de la aplicación y una acción. La función reducer procesa esta acción y devuelve un nuevo estado actualizado de la aplicación.

const reducer = (state, action) => {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
};

En este ejemplo, se utiliza la función reducer para procesar distintas acciones según su tipo, y se hace uso de una estructura switch para ello. En cada caso de acción, se lleva a cabo algún tipo de procesamiento en el estado actual y se devuelve un nuevo estado actualizado.

El último caso de la estructura switch es el default, que se utiliza para manejar cualquier acción que no haya sido contemplada en los casos anteriores. En este caso, simplemente se devuelve el estado actual sin cambios.

Utilizando useReducer

Entonces, para utilizar useReducer, se debe establecer previamente el valor inicial del estado. Luego, se debe definir el reducer (función encargada de cambiar el estado) que se utilizará. Finalmente, se debe llamar a la función dispatch cada vez que se desee actualizar el estado.

A continuación, se muestra un ejemplo de código para llevar a cabo todo esto:

import { useReducer } from "react";

// estado inicial del reducer
const initialState = { count: 0 };

// funcion reducer
const reducer = (state, action) => {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
};

export const Counter = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <h2>Count: {state.count}</h2>
      <button onClick={() => dispatch({ type: "increment" })}>Increment</button>
      <button onClick={() => dispatch({ type: "decrement" })}>Decrement</button>
    </div>
  );
};

En este ejemplo se presenta un componente llamado Counter que utiliza la función useReducer para gestionar su estado interno. Este componente implementa un 'contador', cuyo valor inicial se establece en cero mediante la constante initialState.

La función reducer es responsable de actualizar el estado del contador en función de la acción realizada. En este caso, hay dos acciones posibles: la acción increment, que aumenta el contador en 1, y la acción decrement, que lo disminuye en 1.

useRef

useRef es un hook que permite crear una referencia mutable que persiste durante el ciclo de vida de un componente. Esto puede ser útil para acceder directamente a elementos del DOM, guardar valores que no cambian pero que necesitan ser almacenados de alguna manera, o para guardar referencias a valores que se utilizan en efectos o en otras partes del componente.

Ejemplo de uso real

Uno de los usos más comunes de useRef es para acceder directamente a un elemento del DOM y realizar alguna operación en él. Por ejemplo, si deseamos que un botón tenga el foco cuando un componente se renderiza, podemos usar useRef para almacenar una referencia al elemento del botón y luego usar current para asignarle el foco:

import { useRef, useEffect } from "react";

export const MyComponent = () => {
  // creamos useRef con un valor inicial de 'null'
  const buttonRef = useRef(null);

  useEffect(() => {
    // activamos el "focus" del botón
    // al renderizarseel componente
    buttonRef.current.focus();
  }, []);

  return (
    <div>
      <button ref={buttonRef}>Haz clic aquí</button>
    </div>
  );
};

En este ejemplo, creamos una referencia mutable llamada buttonRef utilizando useRef, la cual se inicializa con el valor 'null'. Luego, en el efecto, utilizamos buttonRef.current para acceder directamente al elemento de botón y llamar al método focus() en él. Finalmente, en la propiedad ref del elemento button, debemos asignarle el valor de buttonRef, lo que permite a React asignar el elemento a la propiedad current de nuestra referencia y así mantener su referencia actualizada.

Al utilizar useEffect con un array de dependencias vacío, éste solo se ejecutará la primera vez que se renderice el componente. Esto permitirá que se aplique el 'focus' sobre el botón en ese momento.

useCallback

useCallback es un hook que ayuda a mejorar el rendimiento de los componentes que utilizan funciones como propiedades.

Cuando creamos una nueva instancia de una función en cada renderizado de un componente, esto puede generar una sobrecarga innecesaria y afectar el rendimiento del sitio web. Utilizando useCallback, podemos crear una instancia de la función solo cuando cambia una de sus dependencias, lo que nos ayuda a evitar esta sobrecarga y mejorar el rendimiento.

Utilizar useCallback

Para utilizar useCallback, simplemente envuelve la función que deseas optimizar con useCallback y proporciona las dependencias como un arreglo de dependencias. La función solo se volverá a crear si alguna de sus dependencias cambia.

import { useState, useCallback } from "react";

export const MyComponent = () => {
  // inicializamos el estado en '0'
  const [count, setCount] = useState(0);

  // memorizamos la función
  const handleClick = useCallback(() => {
    console.log(`El contador es ${count}`);
  }, [count]);

  return (
    <div>
      <p>Contador: {count}</p>
      <button onClick={handleClick}>Incrementar contador</button>
    </div>
  );
};

En este ejemplo, utilizamos useCallback para crear una instancia de la función handleClick solamente cuando la variable count cambie. Pasamos 'count' como la única dependencia del hook, lo que significa que 'handleClick' solo se volverá a crear si 'count' cambia, evitando así re-renderizados innecesarios.

Utilizando useCallback, podemos mejorar significativamente el rendimiento de nuestros componentes y garantizar que nuestro sitio web tenga una mejor experiencia de usuario.

useMemo

Cuando utilizamos useMemo, podemos memorizar el resultado de una función y almacenar su valor en una constante. De esta manera, si el componente se vuelve a renderizar, React comprueba si los valores de entrada de la función han cambiado. Si no hay cambios, useMemo devuelve el valor memorizado sin tener que ejecutar nuevamente la función, lo que puede mejorar significativamente el rendimiento de la aplicación.

Caso de uso real

Un caso frecuente en el cuál se utiliza useMemo es cuando se necesita ordenar una lista. En lugar de ordenar la lista en cada renderizado, useMemo permite memorizar la lista ordenada y evitar cálculos innecesarios. A continuación, se muestra un ejemplo ilustrativo:

import { useMemo } from "react";

const UserList = ({ users }) => {
  // solo se vuelve a ejecutar cuando la propiedad 'users' cambie
  const sortedUsers = useMemo(() => {
    return [...users].sort((a, b) => a.name.localeCompare(b.name));
  }, [users]);

  return (
    <ul>
      {sortedUsers.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

En este ejemplo, hemos utilizado useMemo para memorizar la lista de usuarios ordenada alfabéticamente según el valor de la propiedad name. La función que realiza esta operación se ejecutará únicamente cuando el array de 'usuarios' cambie, y su resultado se almacenará en la constante sortedUsers.

Si el componente se renderiza de nuevo por cualquier otra razón, useMemo devolverá directamente la lista ordenada que se ha memorizado, en lugar de ejecutar nuevamente la función, ahorrando así recursos y mejorando el rendimiento del componente.

Conclusiones

En este artículo, hemos explorado algunos de los hooks más importantes de React: useState, useEffect, useContext y useReducer. Estos hooks proporcionan herramientas poderosas para crear componentes interactivos, manejar efectos secundarios y compartir datos entre componentes.

El hook useState es ideal para manejar el estado interno de un componente funcional, permitiendo almacenar y actualizar datos de manera sencilla. Por otro lado, useEffect es útil para manejar efectos secundarios como llamadas a APIs, actualizaciones del DOM y más.

El hook useContext nos permite acceder al contexto dentro de un componente, evitando la necesidad de pasar datos manualmente a través de props. Y finalmente, useReducer es útil para manejar estados más complejos en los que se requiere una función separada para actualizar el estado.

Estos hooks son herramientas esenciales en el kit de desarrollo de React y te permiten escribir código más limpio, modular y fácil de mantener. A medida que te familiarices con estos hooks y los incorpores en tus proyectos, verás cómo mejoran la eficiencia y calidad de tus aplicaciones.

En resumen, los hooks de React son una característica poderosa que te ayudará a construir aplicaciones más eficientes y de alta calidad. ¡No dudes en explorar más sobre ellos y experimentar con su uso en tus proyectos!