Reducir INP: optimización de event handlers
Aplique debounce a los handlers costosos, utilice scheduler.yield() y evite tareas largas que bloqueen el hilo principal.
Reducir INP: optimización de event handlers es una lección gratuita de React Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de React Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de React Academy incluye 4 lecciones en total.
¿Qué es INP?
Interaction to Next Paint (INP) mide la latencia desde una interacción del usuario, como un clic, toque o pulsación de tecla, hasta que el navegador pinta la respuesta. Un INP > 200ms se percibe como lento.
Por qué los eventos de React pueden ser lentos
Los controladores de eventos de React que realizan demasiado trabajo de forma síncrona bloquean el hilo principal. El navegador no puede pintar la respuesta hasta que termina la tarea de JavaScript, lo que provoca un INP elevado.
Debounce de entradas de texto
Aplique debounce a las operaciones costosas, como llamadas a una API de búsqueda o cálculos complejos, que se desencadenan al pulsar teclas. Las actualizaciones de estado de React en cada pulsación están bien; el trabajo costoso debe aplicar debounce.
import { useDeferredValue, useState } from 'react';
function SearchPage() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query); // defers re-render of slow parts
return (
<>
<input value={query} onChange={e => setQuery(e.target.value)} />
<SearchResults query={deferredQuery} /> {/* re-renders with lower priority */}
</>
);
}useTransition para actualizaciones no urgentes
Incluya las actualizaciones de estado lentas en startTransition para marcarlas como no urgentes. React las pospone y mantiene la entrada de usuario receptiva.
const [isPending, startTransition] = useTransition();
function handleFilter(value) {
setInputValue(value); // urgent — update input immediately
startTransition(() => {
setFilteredList(expensiveFilter(value)); // non-urgent — can be interrupted
});
}Traslado del trabajo pesado fuera del hilo principal
Utilice Web Workers para tareas que requieren muchos cálculos de CPU, como analizar conjuntos de datos grandes o procesar imágenes. El hilo principal permanece receptivo mientras el worker realiza los cálculos.
const worker = new Worker(new URL('./heavy-worker.js', import.meta.url));
function processData(data) {
return new Promise(resolve => {
worker.postMessage(data);
worker.onmessage = e => resolve(e.data);
});
}
// In component:
const handleClick = async () => {
const result = await processData(largeDataset); // doesn't block main thread
setResult(result);
};Cómo evitar tareas largas
Las tareas largas (>50ms) bloquean el hilo principal y aumentan el INP. Divídalas mediante setTimeout, scheduler.yield() o requestIdleCallback.
async function processInChunks(items) {
const CHUNK_SIZE = 100;
for (let i = 0; i < items.length; i += CHUNK_SIZE) {
const chunk = items.slice(i, i + CHUNK_SIZE);
processChunk(chunk);
await new Promise(r => setTimeout(r, 0)); // yield to browser between chunks
}
}scheduler.yield() (API moderna)
scheduler.yield() devuelve el control al bucle de eventos del navegador, lo que permite procesar las interacciones de usuario pendientes antes de reanudar el código.
async function longTask() {
for (const item of largeList) {
processItem(item);
if (/* every N items */) {
await scheduler.yield(); // let browser handle pending clicks/inputs
}
}
}Evite los diseños síncronos en los controladores
La lectura de propiedades de diseño (offsetWidth, getBoundingClientRect()) fuerza un recálculo síncrono del diseño. Agrupe las lecturas antes de las escrituras para evitar el layout thrashing.
// Bad — forces layout recalculation on each iteration:
items.forEach(item => {
const height = item.offsetHeight; // READ — forces layout
item.style.height = height * 2 + 'px'; // WRITE — dirties layout
});
// Good — batch reads, then writes:
const heights = items.map(item => item.offsetHeight); // all reads
heights.forEach((h, i) => items[i].style.height = h * 2 + 'px'); // all writesActions de React 19 para un INP asíncrono
Las Actions de React 19 gestionan mutaciones asíncronas sin bloquear la interfaz; el estado pendiente se actualiza de forma independiente para que la página siga siendo interactiva.
function LikeButton({ postId }) {
const [optimistic, setOptimistic] = useOptimistic(false);
async function handleLike() {
setOptimistic(true);
await likePost(postId); // async — doesn't block
}
return <button onClick={handleLike}>{optimistic ? 'Liked' : 'Like'}</button>;
}Errores comunes de la delegación de eventos
React utiliza delegación de eventos sintéticos: adjunta un único listener a la raíz. Evite adjuntar cientos de listeners DOM individuales en useEffect; utilice en su lugar los eventos sintéticos de React en los elementos JSX.
Medición de INP en DevTools
Utilice el panel Performance de Chrome DevTools para registrar una interacción e inspeccionar las tareas largas. Busque las entradas Interaction en la línea de tiempo y expándalas para encontrar las evaluaciones de scripts que bloquean la ejecución.
Comprobación rápida
¿Qué hook de React marca una actualización de estado como no urgente para que las interacciones del usuario puedan interrumpirla?
Repaso
Reduzca el INP aplicando debounce al trabajo costoso, utilizando startTransition para las actualizaciones no urgentes, delegando el trabajo de CPU a Web Workers y dividiendo las tareas largas con scheduler.yield(). Agrupe las lecturas del DOM antes de las escrituras para evitar el layout thrashing.
Preguntas frecuentes
¿La lección «Reducir INP: optimización de event handlers» es gratis?
Sí — el texto completo de «Reducir INP: optimización de event handlers» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de React Academy, actualiza a CoddyKit PRO. El curso de React Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Reducir INP: optimización de event handlers»?
Aplique debounce a los handlers costosos, utilice scheduler.yield() y evite tareas largas que bloqueen el hilo principal. Practicas React Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar React Academy?
No se requiere experiencia previa. React Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Reducir INP: optimización de event handlers»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de React Academy?
Sí. Cada lección de React Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Medir las Core Web Vitals en aplicaciones React
- Análisis del bundle y estrategia de división de código
- Optimización de imágenes y fuentes en React
- Reducir INP: optimización de event handlers