Manejar el estado en una aplicación de React:¿Cuándo usar useState, React Context y un Manejador de Estado Global en React?

Manejar el estado en una aplicación de React

Manejar el estado en una aplicación de React puede volverse complejo rápidamente, especialmente a medida que crece la aplicación y más componentes necesitan interactuar entre sí. Afortunadamente, React ofrece tres herramientas fundamentales para gestionar el estado: el hook useState, el contexto de React (React Context), y los manejadores de estado globales, como Redux, Zustand o Jotai. Cada una de estas herramientas tiene casos de uso específicos, y saber cuándo emplearlas puede ser clave para mantener tu código limpio y eficiente. En este artículo, exploraremos cuándo es apropiado usar cada una de estas herramientas con ejemplos prácticos.

1. Manejador de Estado Global

¿Qué es?

Los manejadores de estado global, como Redux, Zustand o Jotai, están diseñados para manejar el estado que debe ser accesible desde múltiples partes de una aplicación. Este tipo de estado suele ser persistente y sufre modificaciones frecuentes desde distintos componentes, lo que requiere una gestión centralizada.

Cuándo usar un manejador de estado global:

  1. Aplicaciones grandes y complejas: Si estás construyendo una aplicación a gran escala donde muchos componentes necesitan acceder al mismo estado, un manejador de estado global es ideal.
  2. Estado compartido y persistente: Es útil cuando múltiples partes de la aplicación necesitan interactuar con el mismo estado. Por ejemplo, una aplicación de comercio electrónico puede tener un carrito de compras que debe ser accesible desde diferentes páginas y componentes.
  3. Estados avanzados: Si necesitas manejar operaciones complejas, como la sincronización de múltiples fuentes de datos, middleware o asincronía avanzada, un manejador de estado global te ofrece herramientas más robustas que las opciones locales como useState.

Ejemplos de uso:

  • Autenticación global: En una aplicación donde los usuarios deben autenticarse, el estado de autenticación debe estar disponible en cualquier parte de la aplicación (por ejemplo, para mostrar el nombre del usuario en la barra de navegación o para proteger rutas específicas).
  • Carrito de compras en una tienda online: El carrito puede ser accedido desde diferentes páginas (productos, detalles del producto, checkout, etc.), lo que hace necesario un estado global.

Caso práctico:

import { createStore } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';

// Reducer para manejar el estado del carrito de compras
const cartReducer = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TO_CART':
      return [...state, action.payload];
    default:
      return state;
  }
};

// Crear el store
const store = createStore(cartReducer);

// Componente que interactúa con el carrito global
const Product = () => {
  const dispatch = useDispatch();
  const addToCart = (product) => {
    dispatch({ type: 'ADD_TO_CART', payload: product });
  };

  return <button onClick={() => addToCart('Producto 1')}>Agregar al carrito</button>;
};

// Componente que muestra el contenido del carrito
const Cart = () => {
  const cart = useSelector((state) => state);
  return <div>Items en el carrito: {cart.length}</div>;
};

// Aplicación principal
const App = () => (
  <Provider store={store}>
    <Product />
    <Cart />
  </Provider>
);

2. Hook useState

¿Qué es?

El hook useState es una herramienta simple para manejar el estado local en un componente. Se utiliza para almacenar y actualizar el estado que solo es relevante para un componente específico o para un grupo pequeño de componentes estrechamente relacionados.

Cuándo usar useState:

  1. Estado local: Usa useState cuando el estado es local y específico de un solo componente o de un pequeño conjunto de componentes que están estrechamente relacionados, como un componente padre y sus hijos directos.
  2. Simplicidad: Cuando tu estado es simple y no necesitas compartirlo entre múltiples componentes a lo largo de la aplicación, useState es una opción directa y eficiente.
  3. Componentes aislados: Si un componente puede manejar su propio estado sin necesidad de comunicarlo a otros componentes en el árbol, entonces useState es la mejor opción.

Ejemplos de uso:

  • Formularios: Un componente de formulario que maneja el estado de los campos dentro de sí mismo.
  • Modales y notificaciones: Mostrar u ocultar un modal o una notificación dentro de un componente específico.

Caso práctico:

import React, { useState } from 'react';

const Modal = () => {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsOpen(true)}>Abrir Modal</button>
      {isOpen && (
        <div>
          <p>Este es un modal</p>
          <button onClick={() => setIsOpen(false)}>Cerrar Modal</button>
        </div>
      )}
    </div>
  );
};

export default Modal;

3. React Context

¿Qué es?

React Context es una herramienta que permite compartir datos entre componentes sin tener que pasar props manualmente a través de cada componente intermedio. Ayuda a evitar el “prop-drilling” (la necesidad de pasar props de un componente a otro en una cadena larga de componentes).

Cuándo usar React Context:

  1. Estado global ligero: Si necesitas compartir estado entre múltiples componentes pero no es lo suficientemente complejo como para requerir un manejador de estado global, React Context es ideal.
  2. Evitar prop-drilling: Si pasar props entre múltiples niveles de componentes se vuelve complicado, React Context te permite compartir los datos directamente en los componentes que los necesitan.
  3. Estado estático o semi-estático: Es útil para compartir datos que no cambian frecuentemente, como la configuración de un tema o la selección de un idioma.

Ejemplos de uso:

  • Temas de la aplicación: Cambiar entre temas claros y oscuros en toda la aplicación.
  • Configuraciones de idioma: Proveer una configuración de idioma que se comparte entre varios componentes sin necesidad de pasar props.

Caso práctico:

import React, { createContext, useContext, useState } from 'react';

// Crear el contexto para el tema
const ThemeContext = createContext();

const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

const ThemeSwitcher = () => {
  const { theme, setTheme } = useContext(ThemeContext);

  return (
    <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
      Cambiar a {theme === 'light' ? 'oscuro' : 'claro'}
    </button>
  );
};

const App = () => (
  <ThemeProvider>
    <ThemeSwitcher />
  </ThemeProvider>
);

export default App;

Comparación rápida:

  • useState: Para manejar el estado local, específico de un componente o de sus hijos inmediatos. Es la opción más sencilla cuando el estado no necesita ser compartido entre múltiples componentes.
  • React Context: Ideal para compartir datos entre múltiples componentes sin necesidad de prop-drilling, especialmente cuando el estado no cambia frecuentemente o es relativamente simple.
  • Manejador de estado global: Útil en aplicaciones grandes y complejas donde múltiples componentes necesitan acceder y modificar el mismo estado, especialmente cuando el estado se actualiza con frecuencia o requiere operaciones avanzadas.

Manejar el estado en una aplicación de React

Elegir la herramienta adecuada para manejar el estado en tu aplicación React depende del tamaño de la aplicación y la complejidad del estado que necesitas manejar. Usa useState para estados locales simples, React Context para compartir datos entre múltiples componentes sin complicaciones, y un manejador de estado global para aplicaciones grandes y complejas con necesidades avanzadas de sincronización y persistencia del estado.


Comentarios

Para comentar debes Iniciar sesión o registrarte.