Reduzindo o INP: otimização de manipuladores de eventos
Aplique debounce a manipuladores pesados, use scheduler.yield() e evite tarefas longas que bloqueiem a thread principal.
Reduzindo o INP: otimização de manipuladores de eventos é uma aula grátis de React Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de React Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de React Academy inclui 4 aulas no total.
O que é INP?
Interaction to Next Paint (INP) mede a latência desde uma interação do usuário (clique, toque ou pressionamento de tecla) até o momento em que o navegador renderiza a resposta. Um INP > 200ms transmite lentidão.
Por que os eventos do React podem ser lentos
Manipuladores de eventos do React que realizam trabalho excessivo de forma síncrona bloqueiam a thread principal. O navegador não pode renderizar a resposta até que a tarefa de JS seja concluída, causando um INP alto.
Debounce de entradas digitadas
Aplique debounce a operações dispendiosas (chamadas à API de pesquisa e cálculos pesados) acionadas pela digitação. Atualizar o estado do React a cada tecla é aceitável; o trabalho dispendioso é que deve passar por 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 atualizações não urgentes
Envolva atualizações de estado lentas em startTransition para marcá-las como não urgentes. O React as adia, mantendo a entrada responsiva.
const [isPending, startTransition] = useTransition();
function handleFilter(value) {
setInputValue(value); // urgent — update input immediately
startTransition(() => {
setFilteredList(expensiveFilter(value)); // non-urgent — can be interrupted
});
}Transferência de trabalho pesado para fora da thread principal
Utilize Web Workers para tarefas que exigem muito da CPU (análise de conjuntos de dados grandes e processamento de imagens). A thread principal permanece responsiva enquanto o worker realiza os 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);
};Como evitar tarefas longas
Tarefas longas (>50ms) bloqueiam a thread principal e aumentam o INP. Divida-as utilizando setTimeout, scheduler.yield() ou 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() devolve o controle ao loop de eventos do navegador, permitindo que interações pendentes do usuário sejam processadas antes que o código continue.
async function longTask() {
for (const item of largeList) {
processItem(item);
if (/* every N items */) {
await scheduler.yield(); // let browser handle pending clicks/inputs
}
}
}Evite layouts síncronos nos manipuladores
Ler propriedades de layout (offsetWidth, getBoundingClientRect()) força um recálculo síncrono do layout. Agrupe as leituras antes das gravações para evitar recalculações excessivas do layout.
// 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 do React 19 para INP assíncrono
As Actions do React 19 lidam com mutações assíncronas sem bloquear a interface — o estado pendente é atualizado de forma independente para que a página permaneça interativa.
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>;
}Armadilhas da delegação de eventos
O React utiliza delegação de eventos sintéticos (anexa um único listener à raiz). Evite anexar centenas de listeners individuais do DOM em useEffect — utilize os eventos sintéticos do React nos elementos JSX.
Medição do INP no DevTools
Utilize o painel Performance do Chrome DevTools para registrar uma interação e inspecionar as tarefas longas. Procure entradas de 'Interaction' na linha do tempo e expanda-as para encontrar avaliações de scripts que bloqueiam a execução.
Verificação rápida
Qual hook do React marca uma atualização de estado como não urgente para que ela possa ser interrompida por interações do usuário?
Recapitulação
Reduza o INP aplicando debounce ao trabalho dispendioso, utilizando startTransition para atualizações não urgentes, transferindo o trabalho da CPU para Web Workers e dividindo tarefas longas com scheduler.yield(). Agrupe as leituras do DOM antes das gravações para evitar recalculações excessivas do layout.
Perguntas Frequentes
A aula “Reduzindo o INP: otimização de manipuladores de eventos” é grátis?
Sim — o texto completo de “Reduzindo o INP: otimização de manipuladores de eventos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de React Academy, atualize para CoddyKit PRO. O curso de React Academy inclui 4 aulas no total.
O que vou aprender em “Reduzindo o INP: otimização de manipuladores de eventos”?
Aplique debounce a manipuladores pesados, use scheduler.yield() e evite tarefas longas que bloqueiem a thread principal. Você pratica React Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar React Academy?
Nenhuma experiência prévia é necessária. React Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Reduzindo o INP: otimização de manipuladores de eventos”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de React Academy?
Sim. Cada aula de React Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Medindo os Core Web Vitals em aplicativos React
- Análise do pacote e estratégia de divisão de código
- Otimização de imagens e fontes no React
- Reduzindo o INP: otimização de manipuladores de eventos