Transiciones: useTransition y useDeferredValue

Aprende a hacer actualizaciones no bloqueantes y a suavizar interfaces con useTransition y useDeferredValue.

Cuando una actualización es pesada, no todo cambio debe tratarse con la misma prioridad.

Ahí entran las transiciones.


useTransition

Sirve para marcar ciertas actualizaciones como no urgentes.

import { useState, useTransition } from 'react';

function SearchTabs() {
  const [tab, setTab] = useState('overview');
  const [isPending, startTransition] = useTransition();

  function handleChange(nextTab) {
    startTransition(() => {
      setTab(nextTab);
    });
  }

  return (
    <>
      <button onClick={() => handleChange('posts')}>Posts</button>
      {isPending && <p>Cargando vista...</p>}
      <section>{tab}</section>
    </>
  );
}

Úsalo cuando el cambio afecta a una parte pesada de la UI y no quieres bloquear la interacción principal.


useDeferredValue

Sirve para retrasar la actualización de una parte derivada de la UI.

import { useDeferredValue, useState } from 'react';

function SearchPage() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);

  return (
    <>
      <input value={query} onChange={(e) => setQuery(e.target.value)} />
      <Results query={deferredQuery} />
    </>
  );
}

Es útil cuando quieres que el input responda rápido aunque el listado asociado tarde más en recalcularse.


Diferencia rápida

  • useTransition: difieres una actualización de estado
  • useDeferredValue: difieres un valor ya calculado o recibido

Cuándo no usar estas APIs

  • para micro-optimizaciones sin problema real
  • si el cuello de botella viene de diseño pobre del componente
  • como sustituto de paginación, memoización o división de UI

En la siguiente lección veremos patrones de composición que suelen arreglar más problemas que cualquier hook “mágico”.