Debounce em JavaScript: Otimize Inputs e Scrolls Fácil

Se você já lidou com eventos que disparam inúmeras vezes em milissegundos, como por exemplo, digitar em um campo de busca ou rolar uma página, provavelmente já sentiu o impacto de uma função sendo chamada com muita frequência. O resultado? Travamentos, lentidão e uma aplicação que parece mal otimizada.

São nesses casos que entra o Debounce, que é uma técnica simples, mas muito útil, para melhorar o desempenho da sua aplicação e reduzir chamadas desnecessárias.

Foto de Pankaj Patel na Unsplash

O que é Debounce?

Debounce é uma forma de “segurar” a execução de uma função até que o usuário pare de realizar uma determinada ação.
Em outras palavras, ele garante que uma função só será chamada depois de um pequeno intervalo sem novas execuções.

Vamos imaginar um campo de busca que dispara uma requisição a cada tecla digitada. Se o usuário digita “javascript”, isso pode gerar 10 requisições para o servidor, uma por letra. Com debounce, você espera o usuário terminar de digitar – e então dispara apenas uma requisição.

Exemplo de Campo de busca com loading

Exemplo prático: debounce em sua forma pura (sem bibliotecas)

A implementação mais comum e didática usa setTimeout e clearTimeout.

JavaScript
function debounce(func, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => func.apply(this, args), delay);
  };
}

Vamos usar isso em um campo de busca:

JavaScript
const input = document.querySelector("#search");

const handleSearch = debounce((event) => {
  console.log("Buscando por:", event.target.value);
}, 500);

input.addEventListener("input", handleSearch);

O que está acontecendo aqui:

  • Cada vez que o usuário digita, o setTimeout é reiniciado.
  • Só quando o usuário para de digitar por 500ms, a função realmente roda.
  • Assim, você evita chamadas repetidas e melhora o desempenho.

Onde o Debounce é útil

Debounce é essencial quando você quer reagir apenas depois de o usuário parar de interagir.
Alguns exemplos práticos:

  • Campos de busca que fazem requisições para APIs;
  • Scroll ou resize da janela (para evitar cálculos a cada pixel rolado);
  • Validação de formulários enquanto o usuário digita;
  • Reajustes de layout após o redimensionamento da tela.

Implementando Debounce com React Hooks

Em aplicações React, é comum encapsular o debounce em um Hook reutilizável. Este é um exemplo simples de um useDebounce:

JavaScript
import { useEffect, useState } from "react";

export function useDebounce(value, delay = 500) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

Uso prático:

JavaScript
function SearchInput() {
  const [query, setQuery] = useState("");
  const debouncedQuery = useDebounce(query, 500);

  useEffect(() => {
    if (debouncedQuery) {
      console.log("Buscando:", debouncedQuery);
      // fetch(`/api/search?q=${debouncedQuery}`)
    }
  }, [debouncedQuery]);

  return (
    <input
      value={query}
      onChange={(e) => setQuery(e.target.value)}
      placeholder="Digite algo..."
    />
  );
}

O useDebounce evita que a função de busca seja executada a cada tecla digitada. Ela só dispara quando o usuário para de digitar.


Debounce vs Throttle: Qual a diferença?

Este é um ponto muito importante, pois apesar de serem parecidos na implementação, atuam em finalidades diferentes.

  • Debounce: executa depois que o usuário para de interagir.
  • Throttle: executa em intervalos fixos, mesmo que o evento continue disparando.

Use debounce quando o foco for reduzir chamadas até a última interação (ex: busca, resize).
Use throttle quando quiser limitar a frequência de execução (ex: scroll contínuo, tracking de mouse).


Cuidados e desvantagens

Debounce é ótimo, mas pode existem alguns pontos que não podem ser negligenciados:

  • Pode atrasar a execução em situações onde a resposta precisa ser imediata;
  • O tempo (delay) precisa ser calibrado com cuidado – muito curto e não resolve, muito longo e gera lentidão percebida;
  • Em componentes React, o uso incorreto pode causar re-renderizações desnecessárias ou perda de estado.

Conclusão

O debounce é uma técnica simples, mas essencial para aplicações frontend. Ele melhora o desempenho, economiza recursos e proporciona uma experiência mais fluida para o usuário.

Comece implementando com setTimeout e clearTimeout, e conforme evoluir, crie Hooks personalizados ou utilitários reutilizáveis no seu projeto. É uma daquelas otimizações pequenas que fazem toda a diferença.


Referências

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *