//
Busque em todas as páginas da documentação
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
// React 19: ref é apenas uma prop
function TextInput({ placeholder, ref }: { placeholder: string; ref?: React.Ref<HTMLInputElement> }) {
return <input placeholder={placeholder} ref={ref} />;
}
// Uso -- idêntico a antes
import { useRef } from "react";
function App() {
const inputRef = useRef<HTMLInputElement>(null);
return (
<div>
<TextInput ref={inputRef} placeholder="Digite aqui..." />
<button onClick={() => inputRef.current?.focus()}>Focar</button>
</div>
);
}Quando usar este padrão: Use este padrão para qualquer componente de função que precise expor um nó DOM ou um handle imperativo a um componente pai. Ele substitui forwardRef completamente.
// Uma biblioteca de componentes de input reutilizáveis com suporte a ref
"use client";
import { useRef, useImperativeHandle, type Ref, type ReactNode } from "react";
// Encaminhamento simples de ref -- sem necessidade de wrapper forwardRef
function Input({
label,
error,
ref,
...inputProps
}: {
label: string;
error?: string;
ref?: Ref<HTMLInputElement>;
} & React.InputHTMLAttributes<HTMLInputElement>) {
return (
<div className="flex flex-col gap-1">
<label className="text-sm font-medium">{label}</label>
<input
ref={ref}
className={`border rounded p-2 ${error ? "border-red-500" : "border-gray-300"}`}
{...inputProps}
/>
{error && <span className="text-red-500 text-sm">{error}</span>}
</div>
);
}
// Handle imperativo com ref -- também sem necessidade de forwardRef
type ComboboxHandle = {
open: () => void;
close: () => void;
reset: () => void;
};
function Combobox({
options,
ref,
}: {
options: string[];
ref?: Ref<ComboboxHandle>;
}) {
const inputRef = useRef<HTMLInputElement>(null);
const [isOpen, setIsOpen] = useState(false);
const [value, setValue] = useState("");
useImperativeHandle(ref, () => ({
open: () => setIsOpen(true),
close: () => setIsOpen(false),
reset: () => {
setValue("");
setIsOpen(false);
},
}));
return (
<div className="relative">
<input
ref={inputRef}
value={value}
onChange={(e) => setValue(e.target.value)}
onFocus={() => setIsOpen(true)}
/>
{isOpen && (
<ul className="absolute top-full left-0 border bg-white w-full">
{options
.filter((o) => o.toLowerCase().includes(value.toLowerCase()))
.map((option) => (
<li
key={option}
onClick={() => {
setValue(option);
setIsOpen(false);
}}
className="p-2 hover:bg-gray-100 cursor-pointer"
>
{option}
</li>
))}
</ul>
)}
</div>
);
}
// Componente pai usando ambos os componentes
import { useState } from "react";
export default function RegistrationForm() {
const nameRef = useRef<HTMLInputElement>(null);
const comboRef = useRef<ComboboxHandle>(null);
function handleReset() {
nameRef.current?.focus();
comboRef.current?.reset();
}
return (
<form className="space-y-4">
<Input ref={nameRef} label="Nome Completo" placeholder="Jane Doe" />
<Combobox ref={comboRef} options={["Engenharia", "Design", "Produto", "Marketing"]} />
<button type="button" onClick={handleReset}>
Resetar e Focar Nome
</button>
</form>
);
}O que isso demonstra:
Input simples recebendo ref como uma prop regular e encaminhando-o para o <input> nativoCombobox usando useImperativeHandle com ref como uma prop para expor métodos personalizadosuseRef para interagir com nós DOM filhos e handles imperativosforwardRef em lugar nenhumref é tratado como uma prop regular para componentes de função. O React não o remove mais antes de passar as props para o componente.forwardRef ainda funciona e não foi removido, mas é depreciado. Uma versão futura do React o removerá. O React registra um aviso de depreciação em modo de desenvolvimento.ref é incluída no tipo de props do componente automaticamente ao usar React.ComponentProps<typeof MyComponent>.ref como antes -- a ref aponta para a instância da classe. Esta mudança afeta apenas componentes de função.useImperativeHandle(ref, createHandle) continua a funcionar exatamente como antes. A única diferença é de onde ref vem -- uma prop em vez do segundo argumento de forwardRef.Funções de limpeza de ref (novo no React 19):
function MeasuredDiv({ ref }: { ref?: Ref<HTMLDivElement> }) {
return (
<div
ref={(node) => {
// Configuração
if (node) {
console.log("Montado:", node.getBoundingClientRect());
}
// Retorna a função de limpeza (novo no React 19)
return () => {
console.log("Desmontado");
};
}}
>
Conteúdo medido
</div>
);
}Componente genérico com ref:
type ListProps<T> = {
items: T[];
renderItem: (item: T) => ReactNode;
ref?: Ref<HTMLUListElement>;
};
function List<T>({ items, renderItem, ref }: ListProps<T>) {
return (
<ul ref={ref}>
{items.map((item, i) => (
<li key={i}>{renderItem(item)}</li>
))}
</ul>
);
}Migração de forwardRef:
// Antes (React 18)
const Input = forwardRef<HTMLInputElement, InputProps>((props, ref) => {
return <input ref={ref} {...props} />;
});
// Depois (React 19)
function Input({ ref, ...props }: InputProps & { ref?: Ref<HTMLInputElement> }) {
return <input ref={ref} {...props} />;
}Ref<T> (não RefObject<T>) para o tipo da prop: ref?: React.Ref<HTMLInputElement>.React.Ref<T> é uma união de RefCallback<T>, RefObject<T> e null. Isso cobre todos os padrões de uso de ref.ComponentProps, a prop ref é incluída automaticamente nos tipos do React 19.Ref<MyHandle> onde MyHandle é sua interface personalizada.forwardRef funciona, mas exibe um aviso. Correção: Migre movendo ref do segundo argumento de forwardRef para o objeto de props. Execute o codemod do React: npx @react-codemod/cli forward-ref-as-prop.{...props} agora inclui ref se o componente pai passou um. Correção: Desestruture ref explicitamente: const { ref, ...rest } = props.undefined, o React exibirá um aviso. Correção: Certifique-se de que o callback de ref não retorne nada ou retorne uma função de limpeza.ref em um componente de classe ainda aponta para a instância, não para uma prop. Correção: Nenhuma migração é necessária para componentes de classe.forwardRef internamente continuam a funcionar. Você não precisa esperar que elas migrem. Correção: Nenhuma ação necessária.| Abordagem | Quando escolher |
|---|---|
ref como prop (React 19) | Padrão para todos os novos componentes de função |
forwardRef (depreciado) | Código existente que ainda não foi migrado |
useImperativeHandle | Quando você precisa expor uma API personalizada em vez de um nó DOM |
| Callback ref | Quando você precisa executar lógica na montagem/desmontagem do alvo da ref |
| Comunicação baseada em estado | Quando a comunicação pai-filho deve acionar re-renderizações em vez de chamadas imperativas |
forwardRef adicionava complexidade desnecessária de wrapper e tornava as APIs dos componentes mais difíceis de entenderref é tratado como uma prop regular para componentes de função -- o React não o remove maisforwardRef ainda funciona, mas é depreciado e será removido em uma versão futura// Antes (React 18)
const Input = forwardRef<HTMLInputElement, Props>((props, ref) => {
return <input ref={ref} {...props} />;
});
// Depois (React 19)
function Input({ ref, ...props }: Props & { ref?: Ref<HTMLInputElement> }) {
return <input ref={ref} {...props} />;
}useImperativeHandle(ref, createHandle) funciona exatamente como antesref vem das props em vez do segundo argumento de forwardRefopen(), close(), reset()) para componentes pais<div ref={(node) => {
if (node) console.log("Montado:", node);
// Retorna a função de limpeza (novo no React 19)
return () => console.log("Desmontado");
}} />Callbacks de ref agora podem retornar uma função de limpeza, semelhante à limpeza do useEffect.
ref como antes -- a ref aponta para a instância da classenpx @react-codemod/cli forward-ref-as-prop para migrar automaticamenteref do segundo argumento de forwardRef para a desestruturação de propstype ListProps<T> = {
items: T[];
renderItem: (item: T) => ReactNode;
ref?: Ref<HTMLUListElement>;
};
function List<T>({ items, renderItem, ref }: ListProps<T>) {
return (
<ul ref={ref}>
{items.map((item, i) => <li key={i}>{renderItem(item)}</li>)}
</ul>
);
}{...props} agora inclui ref se o componente pai passou um, o que pode encaminhá-lo não intencionalmenteref explicitamente: const { ref, ...rest } = propsref apenas onde pretendidoundefinedReact.Ref<T> (não RefObject<T>) para o tipo da prop: ref?: React.Ref<HTMLInputElement>React.Ref<T> é uma união de RefCallback<T>, RefObject<T> e nullReact.ComponentProps<typeof MyComponent> inclui automaticamente ref no tiporef manualmente ao estender props de componentesref era excluído de ComponentPropsforwardRef internamente continuam a funcionar sem problemasforwardRef é depreciado, mas funcionalRevisado por Chris St. John·Última atualização: 16 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥