Curso react nivel medio

Los Hooks son funciones especiales en React que permiten usar estado y otras características avanzadas en componentes de función, sin necesidad de usar clases. Los Hooks más comunes son useState y useEffect, pero existen otros que nos ayudan a manejar distintos aspectos de nuestras aplicaciones.

1. Introducción a los Hooks

Antes de los Hooks, los componentes de clase eran necesarios para manejar el estado y el ciclo de vida en React. Con los Hooks, podemos hacer esto y más en componentes de función, lo que simplifica el código y mejora la legibilidad.

Reglas de los Hooks:

  1. Los Hooks deben usarse solo en componentes de función.
  2. Deben estar en el nivel superior del componente, nunca dentro de bucles, condicionales o funciones anidadas.

2. Hook useEffect para efectos secundarios

useEffect es un Hook que permite manejar efectos secundarios en los componentes, como hacer peticiones de datos, suscribirse a servicios externos, o manipular el DOM directamente. Este Hook se ejecuta después de que React haya renderizado el componente, y puede configurarse para ejecutarse solo en momentos específicos.

Ejemplo de useEffect:

1import React, { useEffect, useState } from 'react';
2
3function Reloj() {
4  const [hora, setHora] = useState(new Date());
5
6  useEffect(() => {
7    const intervalo = setInterval(() => {
8      setHora(new Date());
9    }, 1000);
10
11    return () => clearInterval(intervalo); // Limpieza del efecto
12  }, []); // El array vacío significa que el efecto solo se ejecuta una vez
13
14  return <h1>{hora.toLocaleTimeString()}</h1>;
15}
16
17export default Reloj;

En este ejemplo:

  • useEffect crea un intervalo que actualiza el estado hora cada segundo.
  • La función de limpieza (clearInterval) se ejecuta cuando el componente se desmonta, evitando que el intervalo siga corriendo en segundo plano.
  • El [] como segundo parámetro indica que el efecto se ejecuta solo al montar el componente.

3. Otros Hooks útiles

  • useContext: Permite acceder a datos compartidos en toda la aplicación sin necesidad de pasar props manualmente a través de cada componente. Es útil para manejar temas (claro/oscuro), idioma, autenticación, etc.

    1const TemaContext = React.createContext();
    2
    3function Componente() {
    4  const tema = useContext(TemaContext);
    5  return <p>El tema actual es {tema}</p>;
    6}
  • useReducer: Es útil para manejar estados complejos, como en aplicaciones con lógica avanzada. Funciona de manera similar a useState, pero utiliza un “reductor” que especifica cómo cambia el estado.

    1const reducer = (state, action) => {
    2  switch (action.type) {
    3    case 'incrementar':
    4      return { contador: state.contador + 1 };
    5    default:
    6      return state;
    7  }
    8};
    9
    10function Contador() {
    11  const [state, dispatch] = useReducer(reducer, { contador: 0 });
    12
    13  return (
    14    <div>
    15      <p>Contador: {state.contador}</p>
    16      <button onClick={() => dispatch({ type: 'incrementar' })}>Incrementar</button>
    17    </div>
    18  );
    19}
  • useRef: Nos da una referencia mutable a un elemento del DOM. Es ideal para acceder directamente a un elemento sin causar un renderizado.

    1function EnfoqueInput() {
    2  const inputRef = useRef();
    3
    4  const enfocar = () => {
    5    inputRef.current.focus();
    6  };
    7
    8  return (
    9    <div>
    10      <input ref={inputRef} placeholder="Escribe algo..." />
    11      <button onClick={enfocar}>Enfocar</button>
    12    </div>
    13  );
    14}
  • useMemo: Memoriza el resultado de una función para evitar cálculos innecesarios en cada renderizado. Se usa cuando una operación es costosa (como un cálculo complejo o procesamiento de listas grandes).

    1const valorMemoizado = useMemo(() => calcularValorComplejo(datos), [datos]);
  • useCallback: Memoriza una función, evitando que se vuelva a crear en cada renderizado, lo que puede ser útil en componentes que reciben funciones como props.

    1const funcionMemoizada = useCallback(() => {
    2  console.log("Función memorizada");
    3}, []);

4. Ejercicio práctico: Fetch de datos usando useEffect

Vamos a crear un componente que obtenga datos de una API usando useEffect. En este ejemplo, haremos una petición a una API de usuarios y mostraremos los nombres en pantalla.

1import React, { useEffect, useState } from 'react';
2
3function ListaDeUsuarios() {
4  const [usuarios, setUsuarios] = useState([]);
5  const [cargando, setCargando] = useState(true);
6
7  useEffect(() => {
8    // Función para obtener datos
9    const obtenerUsuarios = async () => {
10      try {
11        const respuesta = await fetch('https://jsonplaceholder.typicode.com/users');
12        const datos = await respuesta.json();
13        setUsuarios(datos);
14      } catch (error) {
15        console.error("Error al obtener los usuarios:", error);
16      } finally {
17        setCargando(false); // Oculta el mensaje de carga cuando finaliza
18      }
19    };
20
21    obtenerUsuarios();
22  }, []); // El array vacío hace que el efecto se ejecute solo una vez
23
24  return (
25    <div>
26      <h1>Lista de Usuarios</h1>
27      {cargando ? (
28        <p>Cargando...</p>
29      ) : (
30        <ul>
31          {usuarios.map((usuario) => (
32            <li key={usuario.id}>{usuario.name}</li>
33          ))}
34        </ul>
35      )}
36    </div>
37  );
38}
39
40export default ListaDeUsuarios;

En este ejercicio:

  • Creamos dos estados: usuarios para almacenar la lista de usuarios y cargando para controlar si los datos están siendo cargados.
  • useEffect ejecuta obtenerUsuarios solo una vez cuando el componente se monta.
  • obtenerUsuarios es una función asíncrona que hace una petición a la API de usuarios y actualiza el estado usuarios con los datos obtenidos.
  • Si los datos están cargando, mostramos un mensaje de "Cargando...", y cuando terminan de cargar, mostramos la lista de usuarios.

Este ejercicio combina useEffect con una llamada a la API, lo cual es muy común en aplicaciones React para manejar datos dinámicos.

  • Loading...