Especialização Frontend com React & TypeScript • Demonstrações Práticas Executáveis


🎯 Contexto e Objetivo Prático

Manipulação imperativa de foco com useRef tipado e geração determinística de IDs acessíveis para leitores de tela com useId.


💻 Código Fonte React 19 (TSX)

// SearchBarAccessible.tsx
import React, { useRef, useId } from "react";

export function AccessibleSearchBar({ onSearch }: { onSearch: (term: string) => void }) {
  // 1. useId: IDs únicos e sincronizados entre SSR e Hydration
  const inputId = useId();
  const descriptionId = useId();

  // 2. useRef: Referência fortemente tipada ao elemento HTML nativo
  const inputRef = useRef<HTMLInputElement>(null);

  const handleClearAndFocus = () => {
    if (inputRef.current) {
      inputRef.current.value = "";
      inputRef.current.focus(); // Manipulação imperativa segura
    }
  };

  const handleFormSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (inputRef.current) {
      onSearch(inputRef.current.value);
    }
  };

  return (
    <form onSubmit={handleFormSubmit} className="space-y-2 max-w-sm">
      <label htmlFor={inputId} className="block text-sm font-medium text-slate-700">
        Buscar no Repositório:
      </label>

      <div className="flex gap-2">
        <input
          id={inputId}
          ref={inputRef}
          type="search"
          aria-describedby={descriptionId}
          placeholder="Digite um termo..."
          className="flex-1 px-3 py-2 border rounded-lg text-sm focus:ring-2 focus:ring-blue-500"
        />
        <button
          type="button"
          onClick={handleClearAndFocus}
          className="px-3 py-2 bg-slate-100 hover:bg-slate-200 text-xs rounded-lg"
        >
          Limpar
        </button>
      </div>

      <p id={descriptionId} className="text-xs text-slate-500">
        Pressione Enter para confirmar a busca por cursos ou tópicos.
      </p>
    </form>
  );
}

🖥️ Saída de Renderização Visual e Comportamento

[Campo Acessível Renderizado]
Label for="«r1»" -> Input id="«r1»" aria-describedby="«r2»"
Texto auxiliar id="«r2»"
(Foco automático aplicado via inputRef.current.focus() sem re-render)