Hooks Estado y efectos secundarios

Intermedio
React
React
Actualizado: 22/05/2025

¡Desbloquea el curso completo!

IA
Ejercicios
Certificado
Entrar

Manejo de estado local con useState

En React, el hook useState permite añadir estado local a los componentes funcionales. La sintaxis básica de useState es la siguiente:

const [estado, setEstado] = useState(estadoInicial);

Aquí, estado es la variable que contiene el valor actual del estado, y setEstado es la función que se utiliza para actualizar ese estado. El valor estadoInicial es el valor inicial del estado.

A continuación, se muestra un ejemplo de cómo utilizar useState en un componente funcional:

// Contador.jsx
import { useState } from 'react';

export default function Contador() {
  const [contador, setContador] = useState(0);

  const incrementar = () => setContador(contador + 1);
  const decrementar = () => setContador(contador - 1);

  return (
    <div>
      <p>Contador: {contador}</p>
      <button onClick={incrementar}>Incrementar</button>
      <button onClick={decrementar}>Decrementar</button>
    </div>
  );
}

En este ejemplo, Contador es un componente funcional que utiliza useState para manejar el estado del contador. El estado inicial del contador es 0. Las funciones incrementar y decrementar actualizan el estado del contador utilizando setContador.

Es importante destacar que useState puede aceptar una función como argumento para calcular el estado inicial. Esto es útil cuando el cálculo del estado inicial es costoso y no se debe ejecutar en cada renderizado.

const [estado, setEstado] = useState(() => {
  const valorInicial = calcularValorInicial();
  return valorInicial;
});

En este ejemplo, la función calcularValorInicial se ejecuta solo una vez para calcular el estado inicial.

El hook useState también puede manejar estados que son objetos o arrays. Si el estado es un objeto o un array, debes tener cuidado de no mutar el estado directamente. En su lugar, utiliza la función de actualización del estado para crear una nueva copia del estado con los cambios deseados.

// PerfilUsuario.jsx
import { useState } from 'react';

export default function PerfilUsuario() {
  const [usuario, setUsuario] = useState({ nombre: 'Juan', edad: 30 });

  const actualizarNombre = (nuevoNombre) => {
    setUsuario((prevUsuario) => ({
      ...prevUsuario,
      nombre: nuevoNombre,
    }));
  };

  return (
    <div>
      <p>Nombre: {usuario.nombre}</p>
      <p>Edad: {usuario.edad}</p>
      <button onClick={() => actualizarNombre('Carlos')}>Cambiar Nombre</button>
    </div>
  );
}

En este ejemplo, PerfilUsuario es un componente funcional que utiliza useState para manejar el estado del usuario. La función actualizarNombre actualiza el nombre del usuario sin mutar el estado directamente, utilizando la sintaxis de spread para crear una nueva copia del estado con el nuevo nombre.

Manejo de efectos secundarios con useEffect

Guarda tu progreso

Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.

Progreso guardado
Asistente IA
Ejercicios
Iniciar sesión gratis

Más de 25.000 desarrolladores ya confían en CertiDevs

El hook useEffect en React permite gestionar efectos secundarios en los componentes funcionales. Los efectos secundarios incluyen operaciones como el acceso a APIs, suscripción a eventos o manipulación del DOM. useEffect se ejecuta después de cada renderizado y puede configurarse para ejecutarse bajo ciertas condiciones.

La sintaxis básica de useEffect es:

useEffect(() => {
  // Código del efecto
  return () => {
    // Código de limpieza (opcional)
  };
}, [dependencias]);

El primer argumento es una función que contiene el código del efecto. El segundo argumento es un array de dependencias que determina cuándo debe ejecutarse el efecto. Si el array está vacío, el efecto solo se ejecutará una vez después del primer renderizado. Si se omite el array de dependencias, el efecto se ejecutará en cada renderizado.

Ejemplo básico de uso de useEffect:

// ContadorConEfecto.jsx
import { useState, useEffect } from 'react';

export default function ContadorConEfecto() {
  const [contador, setContador] = useState(0);

  useEffect(() => {
    document.title = `Contador: ${contador}`;
  }, [contador]);

  const incrementar = () => setContador(contador + 1);

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

En este ejemplo, el título del documento se actualiza cada vez que cambia el valor del contador. El efecto se ejecuta solo cuando contador cambia, gracias al array de dependencias [contador].

useEffect también puede utilizarse para realizar suscripciones y limpiar recursos. Es importante limpiar los efectos para evitar fugas de memoria. La función de limpieza se define retornando una función dentro del primer argumento de useEffect.

Ejemplo de suscripción y limpieza:

// Reloj.jsx
import { useState, useEffect } from 'react';

export default function Reloj() {
  const [tiempo, setTiempo] = useState(new Date());

  useEffect(() => {
    const intervalo = setInterval(() => {
      setTiempo(new Date());
    }, 1000);

    return () => {
      clearInterval(intervalo);
    };
  }, []);

  return (
    <div>
      <p>Hora actual: {tiempo.toLocaleTimeString()}</p>
    </div>
  );
}

En este ejemplo, el componente Reloj actualiza el tiempo cada segundo utilizando setInterval. La función de limpieza se llama al desmontar el componente para limpiar el intervalo con clearInterval.

useEffect también puede manejar efectos asíncronos, como llamadas a APIs. Para esto, se puede utilizar una función asincrónica dentro del efecto:

// DatosUsuarios.jsx
import { useState, useEffect } from 'react';

export default function DatosUsuarios() {
  const [usuarios, setUsuarios] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      const respuesta = await fetch('https://jsonplaceholder.typicode.com/users');
      const datos = await respuesta.json();
      setUsuarios(datos);
    };

    fetchData();
  }, []);

  return (
    <div>
      <h1>Lista de Usuarios</h1>
      <ul>
        {usuarios.map(usuario => (
          <li key={usuario.id}>{usuario.name}</li>
        ))}
      </ul>
    </div>
  );
}

En este ejemplo, se realiza una llamada a una API para obtener una lista de usuarios. La función fetchData se define dentro del useEffect y se llama inmediatamente para obtener los datos y actualizar el estado.

Ejemplo combinado de useState y useEffect

En esta sección, combinaremos los hooks useState y useEffect para crear un componente que gestione tanto el estado local como los efectos secundarios. Este enfoque es útil cuando se necesita actualizar el estado en respuesta a eventos externos, como una llamada a una API o un temporizador.

Primero, crearemos un componente que obtenga datos de una API y los muestre en pantalla. Utilizaremos useState para almacenar los datos y useEffect para realizar la llamada a la API cuando el componente se monte.

// DatosAPI.jsx
import { useState, useEffect } from 'react';

export default function DatosAPI() {
  const [datos, setDatos] = useState([]);
  const [cargando, setCargando] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const respuesta = await fetch('https://jsonplaceholder.typicode.com/posts');
        if (!respuesta.ok) {
          throw new Error('Error en la solicitud');
        }
        const data = await respuesta.json();
        setDatos(data);
      } catch (error) {
        setError(error.message);
      } finally {
        setCargando(false);
      }
    };

    fetchData();
  }, []);

  if (cargando) {
    return <p>Cargando...</p>;
  }

  if (error) {
    return <p>Error: {error}</p>;
  }

  return (
    <div>
      <h1>Datos de la API</h1>
      <ul>
        {datos.map((dato) => (
          <li key={dato.id}>{dato.title}</li>
        ))}
      </ul>
    </div>
  );
}

En este ejemplo, DatosAPI es un componente que realiza una solicitud a una API para obtener una lista de publicaciones. Utilizamos useState para manejar tres estados:

  1. datos: Almacena los datos obtenidos de la API.
  2. cargando: Indica si los datos están siendo cargados.
  3. error: Almacena cualquier error que ocurra durante la solicitud.

El hook useEffect se utiliza para realizar la llamada a la API cuando el componente se monta. La función fetchData es asincrónica y se encarga de realizar la solicitud, manejar errores y actualizar los estados correspondientes.

El componente devuelve diferentes elementos en función del estado de carga y de la existencia de errores. Si los datos se están cargando, se muestra un mensaje de "Cargando...". Si ocurre un error, se muestra el mensaje de error. Si los datos se han cargado correctamente, se renderiza una lista de elementos.

Este patrón de uso combinado de useState y useEffect es común en aplicaciones React que necesitan manejar tanto el estado local como los efectos secundarios, permitiendo una gestión eficiente y reactiva de los datos y la interfaz de usuario.

Aprendizajes de esta lección

  • Comprender la función y sintaxis básica del hook useState.
  • Implementar manejo de estado local en componentes funcionales.
  • Utilizar funciones en useState para cálculos iniciales de estado.
  • Manejar estados complejos como objetos y arrays.
  • Entender el funcionamiento y sintaxis básica del hook useEffect.
  • Implementar efectos secundarios, como acceso a APIs y manipulación del DOM.
  • Gestionar suscripciones y limpiar efectos para evitar fugas de memoria.
  • Manejar efectos asíncronos con useEffect.
  • Combinar useState y useEffect en un mismo componente.

Completa React y certifícate

Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.

Asistente IA

Resuelve dudas al instante

Ejercicios

Practica con proyectos reales

Certificados

Valida tus conocimientos

Más de 25.000 desarrolladores ya se han certificado con CertiDevs

⭐⭐⭐⭐⭐
4.9/5 valoración