No requiere paquetes extra -- cada patrón en esta página viene con React. Un proyecto estándar de React (Next.js, Vite o CRA) con TypeScript es suficiente.
Los patrones a continuación son formas de pensar sobre componentes -- cómo se componen, cómo comparten estado, dónde colocar los límites de carga y error. No son APIs que instales; son formas reutilizables que reconoces.
Decide quién es propietario del estado del componente: el padre (controlado) o el componente mismo (no controlado).
import { useState } from "react";// Controlado: el padre es propietario del valuefunction ControlledInput({ value, onChange,}: { value: string; onChange: (v: string) => void
Controlado permite que el padre valide, transforme o reinicie el value -- la opción correcta para formularios y asistentes.
No controlado es más simple para widgets autónomos que nunca necesitan coordinación externa.
Ofrece ambos en un componente reutilizable: acepta value/onChange (controlado) o defaultValue (no controlado), nunca los mezcles.
Cambiar de modo durante el ciclo de vida genera una advertencia de "controlado a no controlado" -- elige uno en el montaje y cúmplelo.
El render prop es una función; el componente compartido la llama con estado y helpers.
Los consumidores deciden qué renderizar -- un componente, muchas presentaciones.
Los custom hooks cubren la mayoría de casos que los render props solucionaban, pero los render props siguen brillando para APIs específicas de renderizado (posicionamiento, medición, librerías de movimiento).
Nombra el prop render, children o algo descriptivo (renderItem); sé consistente dentro de un codebase.
Captura errores de renderizado en un subárbol y renderiza un fallback en lugar de una pantalla blanca.
"use client";import { Component, type ReactNode } from "react";interface State { error: Error | null; }class ErrorBoundary extends Component<{ children: ReactNode }, State> { state
Las Error Boundaries deben ser componentes de clase -- getDerivedStateFromError aún no tiene equivalente con hooks.
Capturan errores durante renderizado, métodos del ciclo de vida y constructores -- no manejadores de eventos, código asincrónico o componentes del servidor.
Colócalas en límites significativos: por ruta, por panel, por widget. Una gran Error Boundary en la parte superior oculta demasiado.
Para aplicaciones en producción, usa react-error-boundary (API más ligera y amigable con hooks) e inicia sesión en Sentry/Datadog en componentDidCatch.
Relacionado:Error Boundaries -- react-error-boundary, Next.js error.tsx, logging | Suspense -- el contraparte de carga
Muestra declarativamente un fallback mientras un child asincrónico se resuelve -- sin pasar props isLoading.
"use client";import { Suspense, use } from "react";interface User { id: number; name: string; }function UserCard({ userPromise }: { userPromise: Promise<User
<Suspense fallback={...}> captura componentes children que "suspenden" (Componentes del Servidor esperando datos, Componentes del Cliente leyendo una promise con use).
El fallback se renderiza inmediatamente; el contenido real lo reemplaza cuando el trabajo asincrónico finaliza.
Crea la promise en un padre (a menudo un Componente del Servidor) y pásala -- no la recrees en cada renderizado.
Combina con una <ErrorBoundary> para que las promises rechazadas muestren una UI de error en lugar de propagarse por el árbol.
Una unión discriminada hace imposibles las combinaciones inválidas (loading: true, error: "...", data: "x", isLoading: true).
El reducer es el único lugar donde viven las transiciones -- trivial de testear unitariamente y de dibujar como un diagrama.
Para máquinas de estado más grandes (estados jerárquicos, guards, efectos secundarios), gradúa a XState; la versión pequeña aquí cubre la mayoría de UIs.
Empareja con useTransition o useActionState para disparar cambios de estado desde trabajo asincrónico.
memo(Component) salta re-renderizados cuando los props son referencialmente iguales al renderizado anterior.
Una función flecha inline crearía una nueva referencia en cada renderizado -- useCallback le da una identidad estable para que memo pueda realmente cortocircuitar.
Mide primero: el Profiler de React DevTools te dice qué componentes son costosos antes de que recurras a memo.
Con el Compilador de React (React 19+), a menudo puedes eliminar completamente memo/useCallback/useMemo -- el compilador lo maneja.