Volver al blog

React 19.2: Activity Component y Partial Pre-rendering Cambian Todo

Hola HaWkers, React 19.2 fue lanzado en octubre de 2025 y trajo features que cambian fundamentalmente cómo construimos aplicaciones React. El Activity component y Partial Pre-rendering son game-changers.

Vamos a analizar cada novedad y cómo aplicar en tu próximo proyecto.

La Evolución de React 19

Desde diciembre de 2024, React 19 ha evolucionado rápidamente. Ve el timeline:

Timeline de Lanzamientos

Versiones de React 19:

Versión Fecha Destacados
v19.0.0 Diciembre 2024 Server Components, Actions
v19.1.0 Marzo 2025 Mejoras de performance
v19.2.0 Octubre 2025 Activity, PPR, useEffectEvent

React 19 completa la transición de React para una arquitectura async-first, el mayor cambio desde React Hooks.

Activity Component: Pre-renderización Inteligente

Qué Es el Activity

El componente Activity permite pre-renderizar y mantener partes ocultas de la aplicación renderizadas sin impactar la performance de lo que está visible.

Casos de uso:

  1. Pre-renderizar rutas: Páginas que el usuario probablemente va a acceder
  2. Preservar estado: Mantener estado de partes navegadas
  3. Transiciones suaves: Navegar sin loading
  4. Optimización de UX: Experiencia instantánea

Cómo Funciona

import { Activity } from 'react';

function App() {
  const [currentTab, setCurrentTab] = useState('home');

  return (
    <div>
      <TabBar current={currentTab} onChange={setCurrentTab} />

      {/* Tab activa - renderiza normalmente */}
      <Activity mode={currentTab === 'home' ? 'visible' : 'hidden'}>
        <HomeTab />
      </Activity>

      {/* Tab oculta - pre-renderizada pero no impacta performance */}
      <Activity mode={currentTab === 'profile' ? 'visible' : 'hidden'}>
        <ProfileTab />
      </Activity>

      {/* Tab oculta - estado preservado aunque no visible */}
      <Activity mode={currentTab === 'settings' ? 'visible' : 'hidden'}>
        <SettingsTab />
      </Activity>
    </div>
  );
}

Modos del Activity

Opciones disponibles:

Modo Comportamiento
visible Renderiza normalmente, visible al usuario
hidden Pre-renderizado pero oculto, estado preservado

Beneficios de Performance

Comparación de navegación:

// ANTES: Sin Activity - re-render a cada navegación
function OldApp() {
  const [tab, setTab] = useState('home');

  // Cada cambio de tab destruye y recrea el componente
  return (
    <div>
      {tab === 'home' && <HomeTab />}
      {tab === 'profile' && <ProfileTab />}
    </div>
  );
}

// DESPUÉS: Con Activity - estado preservado
function NewApp() {
  const [tab, setTab] = useState('home');

  // Componentes pre-renderizados, navegación instantánea
  return (
    <div>
      <Activity mode={tab === 'home' ? 'visible' : 'hidden'}>
        <HomeTab />
      </Activity>
      <Activity mode={tab === 'profile' ? 'visible' : 'hidden'}>
        <ProfileTab />
      </Activity>
    </div>
  );
}

Partial Pre-rendering (PPR)

Qué Es PPR

Partial Pre-rendering permite pre-renderizar partes estáticas de la aplicación y servirlas de un CDN, llenando con contenido dinámico después.

El flujo:

  1. Build time: Partes estáticas pre-renderizadas
  2. CDN: Shell servido instantáneamente
  3. Runtime: Contenido dinámico llena el shell
  4. Resultado: Time-to-first-byte mínimo

Implementación Práctica

// page.jsx - Partial Pre-rendering
import { Suspense } from 'react';

// Esta parte es pre-renderizada en el build
export default function ProductPage({ productId }) {
  return (
    <div>
      {/* Header estático - pre-renderizado */}
      <Header />
      <Navigation />

      {/* Contenido dinámico - carga después */}
      <Suspense fallback={<ProductSkeleton />}>
        <ProductDetails productId={productId} />
      </Suspense>

      {/* Reviews dinámicos */}
      <Suspense fallback={<ReviewsSkeleton />}>
        <ProductReviews productId={productId} />
      </Suspense>

      {/* Footer estático - pre-renderizado */}
      <Footer />
    </div>
  );
}

Ganancias de Performance

Métricas observadas:

Métrica Sin PPR Con PPR Mejora
TTFB 800ms 50ms 94%
LCP 2.5s 1.2s 52%
FCP 1.8s 0.3s 83%

Partial Pre-rendering combina lo mejor de SSG y SSR: velocidad de estático con dinamismo de servidor.

useEffectEvent Hook

El Problema Que Resuelve

Antes de useEffectEvent, lidiar con callbacks en effects era problemático:

// ANTES: Problema con dependencias
function ChatRoom({ roomId, onMessage }) {
  useEffect(() => {
    const connection = createConnection(roomId);

    connection.on('message', (msg) => {
      // onMessage cambia a cada render, causando reconexión
      onMessage(msg);
    });

    return () => connection.close();
  }, [roomId, onMessage]); // onMessage como dependencia = problema
}

La Solución Con useEffectEvent

// DESPUÉS: useEffectEvent resuelve
import { useEffectEvent } from 'react';

function ChatRoom({ roomId, onMessage }) {
  // Crea un event handler estable
  const handleMessage = useEffectEvent((msg) => {
    onMessage(msg);
  });

  useEffect(() => {
    const connection = createConnection(roomId);

    connection.on('message', handleMessage);

    return () => connection.close();
  }, [roomId]); // onMessage no necesita ser dependencia!
}

Cuándo Usar

Casos de uso ideales:

  1. Event handlers en effects: Callbacks que no deben re-trigger el effect
  2. Analytics: Tracking que necesita valores actuales
  3. Notificaciones: Handlers que cambian pero no deben reconectar
  4. WebSockets: Callbacks de mensaje estables
// Ejemplo: Analytics sin re-trigger
function ProductPage({ product, analytics }) {
  const trackView = useEffectEvent(() => {
    // Siempre usa el analytics más reciente
    analytics.track('product_view', { id: product.id });
  });

  useEffect(() => {
    trackView();
  }, [product.id]); // analytics no es dependencia
}

cacheSignal API

Qué Es cacheSignal

La API cacheSignal permite crear señales de cache para invalidar datos de forma reactiva.

import { cacheSignal, use } from 'react';

// Crea un signal de cache para productos
const productCache = cacheSignal();

async function fetchProduct(id) {
  const response = await fetch(`/api/products/${id}`);
  return response.json();
}

function ProductDetails({ productId }) {
  // use() con cache signal
  const product = use(fetchProduct(productId), {
    signal: productCache
  });

  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      <button onClick={() => productCache.invalidate()}>
        Recargar
      </button>
    </div>
  );
}

Invalidación Granular

// Invalidar cache específico
productCache.invalidate(); // Invalida todos los productos

// Invalidar por clave
productCache.invalidate(productId); // Invalida producto específico

// Invalidar con condición
productCache.invalidateIf((key) => key.startsWith('featured-'));

Performance Tracks

Debugging de Performance

React 19.2 introdujo Performance Tracks para debugging avanzado de performance.

Lo que muestra:

  1. Render timing: Cuánto tiempo cada componente lleva
  2. Suspense boundaries: Cuándo y por qué suspenden
  3. Transitions: Duración y estados
  4. Effects: Timing de effects y cleanup

Cómo Usar

// Activar Performance Tracks en dev
import { enableProfiler } from 'react-devtools';

enableProfiler({
  tracks: true,
  showSuspenseFallbacks: true,
  highlightUpdates: true
});

Integración Con DevTools

React DevTools 5.x:

  • Visualización de tracks en Profiler
  • Timeline de Suspense
  • Flamegraph mejorado
  • Métricas de re-render

Migrando Para React 19.2

Paso a Paso

1. Actualiza dependencias:

npm install react@19.2.0 react-dom@19.2.0

2. Verifica compatibilidad:

// React 19.2 requiere:
// - Node.js 18+
// - Bundler moderno (Vite, webpack 5+)
// - TypeScript 5.0+ (si usa TS)

3. Adopta features gradualmente:

// Comienza con Activity en áreas de navegación
<Activity mode={isActive ? 'visible' : 'hidden'}>
  <ExpensiveComponent />
</Activity>

// Después agrega PPR en páginas estáticas
// Por último, migra effects para useEffectEvent

Problemas Comunes

Errores frecuentes:

Error Causa Solución
Activity not defined Import faltando import { Activity } from 'react'
Hydration mismatch Server/Client diff Verificar logs de diff
useEffectEvent in non-effect Uso incorrecto Usar apenas para effects

React 19 vs Alternativas

Comparación Con Frameworks

React 19.2 vs otros:

Feature React 19.2 Svelte 5 Vue 3.5 Solid 2
Server Components Parcial Nuxt No
PPR No No No
Activity-like No KeepAlive No
Signals Via hooks Nativo Nativo Nativo

Cuándo Elegir React 19

React 19.2 es ideal para:

  • Aplicaciones enterprise con SSR
  • Dashboards complejos con muchas tabs
  • E-commerce con PPR
  • Apps que necesitan estado preservado

El Futuro de React

Roadmap 2026

Lo que esperar:

  1. React Compiler GA: Optimización automática de memoization
  2. Más APIs de cache: Invalidación aún más granular
  3. Activity mejorado: Más modos y opciones
  4. DevTools AI: Sugerencias de optimización

Impacto en el Mercado

Tendencias:

  • React mantiene posición de líder
  • Next.js como principal framework
  • Server Components como estándar
  • Performance como diferencial

Conclusión

React 19.2 representa la madurez de la visión async-first de React. Activity component y Partial Pre-rendering resuelven problemas reales de UX que desarrolladores enfrentan hace años.

Si aún no migraste para React 19, ahora es el momento. Las features de performance y DX justifican el esfuerzo de actualización.

Para entender más sobre el ecosistema JavaScript en 2025, te recomiendo echar un vistazo al artículo sobre TypeScript Supera Python donde analizamos los lenguajes más usados.

¡Vamos a por ello! 🦅

Comentarios (0)

Este artículo aún no tiene comentarios 😢. ¡Sé el primero! 🚀🦅

Añadir comentarios