0Pricing
React Academy · Aula

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 writes

Actions 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

  1. Medindo os Core Web Vitals em aplicativos React
  2. Análise do pacote e estratégia de divisão de código
  3. Otimização de imagens e fontes no React
  4. Reduzindo o INP: otimização de manipuladores de eventos
← Voltar para React Academy