DevPath · Aprenda a programar ESPTEN

React moderno: Suspense, lazy, Portals e concorrência

Refs avançadas e concorrência

forwardRef: expor uma ref através de um componente

As ref não são passadas como uma prop normal. Se você quer que um componente pai obtenha uma referência a um nó dentro de um componente filho, esse filho deve reencaminhar a ref com React.forwardRef:

const Input = React.forwardRef(function Input(props, ref) {
  return <input ref={ref} {...props} />;
});

function Formulario() {
  const inputRef = React.useRef(null);
  // inputRef.current apontará para o <input> real do filho
  return <Input ref={inputRef} />;
}

useImperativeHandle: personalizar o que a ref expõe

Às vezes você não quer dar acesso ao nó DOM inteiro, mas apenas a algumas ações concretas (uma mini-API imperativa). useImperativeHandle define exatamente o que o pai verá através da ref:

const Campo = React.forwardRef(function Campo(props, ref) {
  const inputRef = React.useRef(null);
  React.useImperativeHandle(ref, () => ({
    focar: () => inputRef.current.focus(),
    limpar: () => { inputRef.current.value = ""; },
  }));
  return <input ref={inputRef} />;
});

// O pai pode chamar campoRef.current.focar() — e nada mais.

É um padrão excepcional: use-o apenas para ações imperativas reais (foco, scroll, reproduzir/pausar). Para dados, continue preferindo props e estado.

Hooks concorrentes: manter a UI responsiva

O React moderno pode interromper e priorizar renderizações. Dois hooks aproveitam isso para que o trabalho custoso não congele a interface:

useTransition

Marca uma atualização de estado como não urgente (uma transição). O React a processa com baixa prioridade, deixando que as interações urgentes (digitar em um input) respondam na hora. Além disso, dá um isPending para mostrar um indicador de carregamento:

const [isPending, startTransition] = useTransition();

function buscar(texto) {
  setTexto(texto);                 // urgente: o input se atualiza já
  startTransition(() => {
    setResultados(filtrar(texto)); // não urgente: pode esperar/ser interrompido
  });
}

useDeferredValue

Recebe um valor e devolve uma versão "atrasada" dele. Enquanto chega um valor novo, o React pode continuar mostrando o anterior, evitando recalcular uma lista pesada a cada tecla pressionada:

const consultaDiferida = useDeferredValue(consulta);
// A lista cara é filtrada com consultaDiferida, não com consulta.

Ambos perseguem o mesmo: que digitar ou clicar se sinta fluido mesmo que haja uma renderização cara em segundo plano.

useId: identificadores únicos e estáveis

React.useId gera um id único e estável para o componente, idêntico no servidor e no cliente (chave para evitar erros de hidratação). Seu uso estrela é a acessibilidade: vincular um <label> com seu <input>.

function Campo() {
  const id = React.useId();
  return (
    <div>
      <label htmlFor={id}>Nome</label>
      <input id={id} />
    </div>
  );
}

Assim você não precisa inventar ids na mão (que colidiriam se o componente for usado várias vezes na página). Nunca use useId para gerar keys de listas: é para ids de elementos do DOM.

No exercício de código você praticará React.useId (síncrono e validável). Os hooks concorrentes useTransition e useDeferredValue são avaliados nos questionários, já que seu efeito depende do agendador assíncrono do React.

Coloque isto em prática

O DevPath é um curso prático: aqui você lê a teoria; no app você a coloca em prática com exercícios que rodam de verdade, offline.

Comece grátis no app →
← Portals: renderizar fora da árvore do DOMVer o módulo →