React State

React Context API

La Context API es la forma nativa de React para compartir estado a través de un árbol de componentes sin pasar props por cada nivel. Bien utilizada, elimina el prop drilling; utilizada descuidadamente, provoca que todo se renderice de nuevo.

intermediate13 min readUpdated 15 sept 2026
ThemeContext.jsx
jsx
// ThemeContext.jsx
import { createContext, useContext } from "react";

const ThemeContext = createContext("light");

export function useTheme() {
  return useContext(ThemeContext);
}

export function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}
Incluido en
React
Paquetes extra
Ninguno
Creado con
createContext
Suministrado por
Context.Provider
Leído con
useContext
Ideal para
Valores compartidos de baja frecuencia

Por que importa

Por qué existe Context

Sin prop drilling

Cualquier componente en el árbol puede leer un valor compartido directamente, sin importar qué tan profundamente esté anidado.

Cero dependencias

Context es parte de React, por lo que no hay nada que instalar ni runtime extra que considerar.

Providers componibles

Puedes anidar varios providers y dividir un valor grande en contextos enfocados para obtener un mejor rendimiento.

La imagen completa

Las tres partes de Context

Un objeto de contexto, un provider que suministra un valor y un hook que lo lee. No hay nada más que aprender.

El objeto de contexto

Identidad

Creado una sola vez con createContext, es la clave que los componentes usan para encontrar un provider.

El provider

Suministro

Un componente que coloca un valor en el árbol y renderiza de nuevo a los consumidores cuando este cambia.

El consumidor

Lectura

useContext lee el valor del provider más cercano, y un hook personalizado envuelve esto por conveniencia.

Context de un vistazo

El núcleo de Context

createContext

Define un contexto con un valor por defecto que se usa cuando no hay ningún provider presente.

Provider

Envuelve un subárbol y pasa el valor actual a cada consumidor inferior.

useContext

Lee el valor del provider más cercano dentro de cualquier componente.

Hooks personalizados

Envuelve useContext en un hook para que quienes lo llamen tengan una API clara y comprobaciones de errores.

División de contextos

Separa el estado y las acciones para que los consumidores solo se rendericen de nuevo por lo que utilizan.

Rendimiento

Context renderiza de nuevo a todos los consumidores al cambiar, así que mantén los valores estables y enfocados.

Una breve historia

De API oculta a funcionalidad de primer nivel

  1. 2018

    Context se vuelve estable

    React 16.3 lanza una Context API soportada después de años de una versión experimental.

    18
  2. 2019

    Llegan los Hooks

    useContext hace que consumir el contexto sea una sola línea de código y reemplaza los render props.

    19
  3. 2021

    Context y rendimiento

    La comunidad adopta la división de contextos y la memoización de valores como mejor práctica.

    21
  4. Hoy

    Una herramienta integrada

    Context es el estándar para temas, auth y locale, mientras que los stores manejan el estado de alta frecuencia.

    Hoy

La guia completa

React Context API: Todo lo que necesitas saber

¿Qué es la Context API?

La Context API es la forma nativa de React para pasar datos a través del árbol de componentes sin tener que pasar props por cada nivel. Resuelve un problema común y específico: un valor que muchos componentes necesitan, pero que se encuentra muy por encima de ellos en el árbol.

El ejemplo clásico es el manejo de temas (theming). Un Button situado en lo profundo del árbol necesita el tema actual, pero cada componente entre la raíz y el botón tendría que aceptar y reenviar una prop theme. A esto se le llama prop drilling, y Context lo elimina. Proporcionas el valor una sola vez y cualquier descendiente puede leerlo directamente.

Creación y provisión de contexto

El contexto consta de tres piezas: un objeto, un proveedor y un hook de consumo.

// AuthContext.jsx
import { createContext, useContext, useMemo, useState } from "react";

const AuthContext = createContext(null);

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);

  const value = useMemo(
    () => ({
      user,
      login: (nextUser) => setUser(nextUser),
      logout: () => setUser(null),
    }),
    [user],
  );

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

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}

createContext define el contexto y un valor predeterminado. El proveedor suministra el valor actual a todo lo que se encuentre debajo de él. El hook personalizado lee el valor y devuelve un error claro si el componente se utiliza fuera del proveedor.

Consumiendo el contexto

Cualquier descendiente puede leer el valor, sin importar qué tan profundo se encuentre.

// Header.jsx
import { useAuth } from "./AuthContext";

export function Header() {
  const { user, logout } = useAuth();

  return (
    <header>
      <span>{user ? `Hi, ${user.name}` : "Guest"}</span>
      {user && <button onClick={logout}>Sign out</button>}
    </header>
  );
}

El Header nunca recibió una prop de App. Accedió directamente al árbol para obtener el valor que necesitaba, lo que evita que los componentes intermedios tengan conocimiento de datos que no utilizan.

El contexto no es estado

Esta distinción suele confundir a muchos. El contexto no mantiene el estado ni gestiona las actualizaciones; lo que hace es transportar un valor. El estado en sí reside en useState o useReducer, y el provider lo distribuye hacia abajo.

Es por eso que un patrón común es combinar el contexto con un reducer:

// CartContext.jsx
import { createContext, useContext, useReducer } from "react";

const CartContext = createContext(null);

function reducer(state, action) {
  switch (action.type) {
    case "add":
      return [...state, action.item];
    case "remove":
      return state.filter((item) => item.id !== action.id);
    default:
      return state;
  }
}

export function CartProvider({ children }) {
  const [items, dispatch] = useReducer(reducer, []);
  return (
    <CartContext.Provider value={{ items, dispatch }}>
      {children}
    </CartContext.Provider>
  );
}

export const useCart = () => useContext(CartContext);

El reducer mantiene las actualizaciones predecibles y el contexto hace que estén disponibles en cualquier lugar sin necesidad de recurrir al prop drilling.

Rendimiento: la verdadera limitación

Cuando el valor de un provider cambia, todos los componentes que consumen ese contexto se vuelven a renderizar. No existen los selectores, por lo que no puedes suscribirte solo a una parte del valor. Hay dos hábitos que permiten mantener esto bajo control.

Memoriza el valor. Un objeto literal crea una nueva referencia en cada renderizado, lo que significa que cada consumidor se re-renderiza incluso cuando nada ha cambiado.

// memoised
const value = useMemo(() => ({ user, logout }), [user]);

Divide los contextos. Coloca el estado y las acciones en contextos separados, o divídelos por funcionalidad, para que un componente que solo necesita ejecutar una acción no se re-renderice cuando el estado cambie.

// split.jsx
const CartStateContext = createContext(null);
const CartActionsContext = createContext(null);

Los componentes que solo llaman a acciones se suscriben al contexto de acciones, el cual nunca cambia su identidad, por lo que nunca se re-renderizan debido a una actualización de estado. Este sencillo truco resuelve la mayoría de las quejas de rendimiento relacionadas con el contexto.

Cuándo usar Context y cuándo no

Context es la herramienta adecuada para:

  • Temas y modo de color.
  • El usuario autenticado y la sesión.
  • Localización y traducciones.
  • Un router o una configuración pequeña y estable.

Recurre a un store dedicado cuando tengas:

  • Actualizaciones frecuentes, como escritura, arrastre (dragging) o animaciones.
  • Un árbol de estado extenso donde los componentes necesiten selectores.
  • Necesidad de middleware, persistencia o devtools de viaje en el tiempo (time-travel).
  • Estado del servidor que requiera almacenamiento en caché (caching) y refetching.

Librerías como Zustand y Redux Toolkit añaden selectores para que los componentes se suscriban a fragmentos (slices) en lugar de a todo el valor. Para los datos del servidor, TanStack Query gestiona el caching por completo.

Mejores prácticas

  • Envuelve useContext en un custom hook y verifica que el provider esté presente.
  • Memoriza los valores del provider con useMemo.
  • Divide los contextos según su responsabilidad, especialmente separando el estado de las acciones.
  • Mantén los valores del contexto pequeños y enfocados.
  • Usa useReducer cuando las actualizaciones sean complejas o dependan del estado anterior.
  • No utilices el contexto para actualizaciones de alta frecuencia; utiliza un store basado en selectores.
  • Define valores predeterminados coherentes para que los componentes puedan renderizarse fuera de un provider cuando sea apropiado.

Errores comunes

  • Tratar el context como un gestor de estado y esperar que tenga selectors.
  • Pasar un objeto inline como valor del provider, provocando que todo se vuelva a renderizar.
  • Colocar datos no relacionados en un único context gigante.
  • Olvidar el valor por defecto y provocar un crash en undefined.
  • Usar context para valores que solo necesitan uno o dos componentes.
  • Esperar que el context optimice los re-renders automáticamente.

Próximos pasos

El Context es la base para compartir el estado en React, y conocer sus límites te indicará cuándo es momento de pasar al siguiente nivel. Compáralo con Redux Toolkit para un estado predecible a gran escala y con Zustand para un store de selectores ligero; luego, gestiona los datos del servidor con TanStack Query. Para Vue, el concepto equivalente se explica en la guía de Pinia.

Compartir un valor

Context es para valores que muchos componentes necesitan, como el tema o el usuario actual. No es un reemplazo para cada prop.

Preferir
const ThemeContext = createContext("light");

function Button() {
  const theme = useContext(ThemeContext);
  return <button className={theme} />;
}
Evitar
function Button({ theme }) {
  return <button className={theme} />;
}
// drilled through every
// level of the tree

Proveer un valor

Un objeto inline crea una nueva referencia en cada renderizado, provocando que cada consumidor se renderice de nuevo. Memoízalo.

Preferir
const value = useMemo(
  () => ({ user, logout }),
  [user],
);

<AuthContext.Provider value={value}>
  {children}
</AuthContext.Provider>
Evitar
<AuthContext.Provider
  value={{ user, logout }}
>
  {children}
</AuthContext.Provider>

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender Context API?

Nuestro tutorial interactivo te guia a traves de Context API paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.