Hook useDeferredValue
Diferir la actualización de una parte de la interfaz para mantener el resto responsivo durante renders costosos.
Busca en todas las páginas de la documentación
Diferir la actualización de una parte de la interfaz para mantener el resto responsivo durante renders costosos.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Tarjeta de referencia rápida - lista para copiar y pegar.
const deferredQuery = useDeferredValue(query);
// El componente que usa deferredQuery se re-renderiza con menor prioridad
<SearchResults query={deferredQuery} />
// Detectar contenido obsoleto
const isStale = deferredQuery !== query;Cuándo usarlo: Tienes un value que cambia rápidamente (como entrada de búsqueda) impulsando un render hijo costoso, y quieres que la entrada permanezca receptiva mientras el hijo se pone al día.
"use client";
import { memo, useDeferredValue, useState } from "react";
const HeavyList = memo(function HeavyList({ query }: { query: string }) {
const items = Array.from({ length: 5000 }, (_, i) => `Result ${i}: ${query}`);
return (
<ul className="max-h-64 overflow-y-auto text-sm">
{items
.filter((item) => item.toLowerCase().includes(query.toLowerCase()))
.slice(0, 100)
.map((item, i) => (
<li key={i} className="py-0.5">{item}</li>
))}
</ul>
);
});
export function DeferredSearch() {
const [query, setQuery] = useState("");
const deferredQuery = useDeferredValue(query);
const isStale = deferredQuery !== query;
return (
<div className="space-y-3">
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Escribe para buscar..."
className="border rounded px-3 py-2 w-full"
/>
<div className={isStale ? "opacity-50 transition-opacity" : "transition-opacity"}>
<HeavyList query={deferredQuery} />
</div>
</div>
);
}Lo que esto demuestra:
query se actualiza instantáneamente en cada pulsación de tecla, manteniendo la entrada receptivadeferredQuery se retrasa, por lo que HeavyList se re-renderiza con menor prioridadReact.memo en HeavyList es esencial - sin él, el componente se re-renderiza con query de todas formasdeferredQuery !== queryuseDeferredValue acepta un value y devuelve una copia diferida del mismo| Parámetro | Tipo | Descripción |
|---|---|---|
value | T | El value que quieres diferir |
initialValue | T (React 19) | Value inicial opcional para el primer renderizado |
| Retorno | Tipo | Descripción |
|---|---|---|
deferredValue | T | La versión diferida del value |
Diferir contenido de Suspense:
function App() {
const [query, setQuery] = useState("");
const deferredQuery = useDeferredValue(query);
return (
<>
<SearchInput value={query} onChange={setQuery} />
<Suspense fallback={<Skeleton />}>
<SearchResults query={deferredQuery} />
</Suspense>
</>
);
}React 19 initialValue (evitar mostrar contenido obsoleto al montar):
// Mostrar resultados vacíos inicialmente, luego llenar con baja prioridad
const deferredItems = useDeferredValue(items, []);Combinando con transition para estado de carga:
const deferredQuery = useDeferredValue(query);
const isStale = deferredQuery !== query;
return (
<div>
{isStale && <p className="text-sm text-gray-400">Cargando...</p>}
<Results query={deferredQuery} />
</div>
);// El tipo se infiere del value de entrada
const deferredQuery = useDeferredValue(query); // string
// React 19 con initialValue
const deferredItems = useDeferredValue<Item[]>(items, []);Olvidar React.memo - useDeferredValue solo ayuda si el componente hijo está memoizado. De lo contrario, el hijo se re-renderiza con el value actual en el primer paso de todas formas. Solución: Envuelve el hijo costoso en React.memo.
No apto para limitar llamadas API - useDeferredValue diferir el renderizado, no el cambio del value en sí. No reduce el número de llamadas fetch. Solución: Usa debounce para llamadas API; usa useDeferredValue para rendimiento de renderizado.
Flash de contenido obsoleto - El value diferido se retrasa detrás del value real, así que los usuarios ven contenido obsoleto brevemente. Solución: Muestra un indicador visual (opacidad, spinner) cuando deferredValue !== value.
Solo valores primitivos - Pasar un nuevo objeto o array en cada renderizado anula el propósito, porque la comparación Object.is encuentra un nuevo value cada vez. Solución: Memoiza objetos o arrays con useMemo antes de pasarlos a useDeferredValue.
| Alternativa | Úsalo Cuando | No lo Uses Cuando |
|---|---|---|
useTransition | Controlas cuándo sucede la actualización de estado y quieres envolverla explícitamente | Recibes el value como prop y no puedes controlar cuándo cambia |
| Debouncing | Quieres reducir el número de actualizaciones de estado o llamadas API | Quieres retroalimentación instantánea con renderizado diferido |
| Virtualización | El cuello de botella es renderizar demasiados nodos DOM | El cuello de botella es computación, no recuento DOM |
| Web Worker | El cálculo pesado debe moverse completamente del hilo principal | El trabajo es renderizado de React |
useDeferredValue vs. useTransition: useTransition envuelve la actualización de estado; useDeferredValue envuelve el consumo del value. Usa useDeferredValue cuando no controlas la actualización de estado (por ejemplo, viene de una prop o padre).
React.memo, el hijo se re-renderiza en cada renderizado padre con el value actual, no el diferido.React.memo salta el re-renderizado cuando las props no han cambiado, permitiendo que el value diferido se retrasar.useDeferredValue no proporciona ningún beneficio de renderizado.const deferredQuery = useDeferredValue(query);
const isStale = deferredQuery !== query;
return (
<div className={isStale ? "opacity-50" : ""}>
<Results query={deferredQuery} />
</div>
);useDeferredValue permite que la actualización de estado suceda inmediatamente pero diferir cuándo el hijo se re-renderiza.useDeferredValue para rendimiento de renderizado.useDeferredValue compara values con Object.is, que verifica igualdad de referencia.{} o array [] creado durante el renderizado siempre tiene una nueva referencia.useMemo antes de pasarlos a useDeferredValue.debounce o throttle en el manejador de entrada.useDeferredValue solo ayuda con renderizado React costoso.// El primer renderizado usa [] en lugar del array de items completo
const deferredItems = useDeferredValue(items, []);useDeferredValue funciona con cualquier componente hijo costoso, no solo los habilitados para Suspense.// El tipo se infiere del value de entrada
const deferredQuery = useDeferredValue(query); // string
// React 19 con initialValue
const deferredItems = useDeferredValue<Item[]>(items, []);useDeferredValue cuando recibes un value que cambia rápidamente como prop y no controlas la actualización de estado.useTransition cuando controlas el setter de estado y quieres envolverla actualización explícitamente.Revisado por Chris St. John·Última actualización: 16 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥