forwardRef, bir ebeveyn bileşenin bir ref'i senin bileşenin üzerinden içindeki bir DOM öğesine aktarmasını sağlar; böylece ebeveyn o öğe üzerinde focus(), scrollIntoView() ve benzeri metotları çağırabilir. React 19'da artık buna ihtiyacın yok: fonksiyon bileşenleri ref'i sıradan bir prop olarak alır. forwardRef hâlâ çalışır ve mevcut kodun çoğunda onu göreceksin, bu yüzden bu sayfa ikisini de gösteriyor.
forwardRef iki argümanlı bir render fonksiyonu alır: props ve ebeveynin aktardığı ref. ref, props'un içinde değildir; ayrı gelir. Focus'a tıkla; konsol inputRef.current'ın gerçek <input> düğümü olduğunu doğrular.
React 19 yolu: ref bir prop'tur
React 19'dan beri bir fonksiyon bileşeni ref'i props'unda diğer her prop gibi alır. Sarmalayıcı yok, ikinci argüman yok:
Bir şey yaz ve Log value'ya tıkla: ebeveyn input'un mevcut metnini doğrudan DOM düğümünden okur. <input>'tan ref={ref}'i sil ve Focus'a tıkla: konsol bir hata gösterir, çünkü inputRef.current artık null'dır.
forwardRef (tüm sürümler) | ref prop'u (React 19+) | |
|---|---|---|
| Bileşen ref'i nasıl alır | İkinci argüman, (props, ref) | props.ref |
| Sarmalayıcı gerekli mi | Evet | Hayır |
useImperativeHandle ile çalışır mı | Evet | Evet |
| Durum | Çalışıyor, kullanımdan kaldırılması planlanıyor | Yeni kod yazmanın yolu |
Çocuğun yok saydığı bir ref null kalır
Bir bileşene ref aktarmak tek başına hiçbir şey yapmaz. Bileşenin onu bir öğeye koyması gerekir. Koymazsa ref.current null kalır:
Konsol Forgetful ref: null ve Careful ref: INPUT gösterir. Bu, özel bir bileşende "ref.current is null" görmenin en yaygın nedenidir. React 19'dan önce, forwardRef ile sarılmadıkça Careful da null olurdu, çünkü ref fonksiyona hiç verilmezdi.
useImperativeHandle: daha küçük bir API açığa çıkar
Ebeveyne tüm DOM düğümünü vermek ona her şeyi yapabilmesi demektir: stilleri değiştirmek, çocukları kaldırmak, gizli tutmak istediğin değerleri okumak. useImperativeHandle bunun yerine ref.current'ın neyi içereceğine senin karar vermeni sağlar:
Son düğme ["focus", "clear"] yazar: ebeveyn input düğümünü değil, bu iki metodu alır, başka bir şeyi değil. Nesneye bir select() metodu ve onu çağıran bir düğme ekle; ebeveyn tam olarak bir yetenek daha kazanır.
Çocuk gerçek input için kendi ref'ini, inputRef, tutar ve handle onu sarar. Üçüncü argüman useEffect'teki gibi bir bağımlılık dizisidir: bu değerler değiştiğinde handle yeniden oluşturulur.
Buna idareli başvur. Bir ebeveynin istediği çoğu şey (açmak, kapatmak, bir hata göstermek) isOpen ya da error gibi props olarak daha iyidir. İmperatif metotlar doğal bir prop'u olmayan eylemler içindir: odaklanmak, kaydırmak, bir video oynatmak, bir animasyon başlatmak.
Ref'i çocuğun içinde de kullanmak
Bazen çocuğun kendi işi için aynı DOM düğümüne ihtiyacı vardır, örneğin onu ölçmek ya da bir hatadan sonra ona odaklanmak için, ebeveyn de ona bir ref tutarken. Tek bir ref özelliği yalnızca tek bir değer alabilir, bu yüzden ikisini bir ref callback'i ile birleştir:
function AutoGrowTextarea({ ref, ...props }) {
const localRef = useRef(null);
function setRefs(node) {
localRef.current = node;
if (typeof ref === 'function') ref(node);
else if (ref) ref.current = node;
}
return <textarea ref={setRefs} {...props} />;
}
Ebeveynin ref'i useRef'ten gelen bir nesne ya da bir fonksiyon olabilir, bu yüzden ikisini de ele al. Ebeveynin yalnızca birkaç eyleme ihtiyacı olduğunda yukarıdaki useImperativeHandle daha temiz bir seçimdir, çünkü çocuk düğümü kendine saklar.
Bir ref'i birkaç katmandan geçirmek
Bir ref her seferinde bir bileşen ilerler. Form, Field'ı render ediyorsa, o TextInput'u, o da <input>'u render ediyorsa, bu bileşenlerin her biri ref'i bir sonrakine aktarmak zorundadır. React 19'da bu, iletilecek bir prop daha demektir (<TextInput ref={ref} />); forwardRef ile her katmanın sarılması gerekiyordu. Eski sürümlerde props'u yaymak ({...props}) onu taşımaz, çünkü React 19'dan önce ref hiçbir zaman props'un parçası değildi.
Bunun önemli olduğu olağan yer tasarım sistemi bileşenleridir: yerel bir öğeyi saran bir Button, Input ya da Select ref'ini iletmelidir; böylece onu kullanan uygulama ona odaklanabilir, onu ölçebilir ya da açılır pencereleri konumlandıran bir kütüphaneye verebilir.
forwardRef'ten geçiş
Değişiklik mekaniktir: sarmalayıcıyı kaldır ve ref'i props'tan oku.
// Before
const Button = forwardRef(function Button({ variant, ...props }, ref) {
return <button ref={ref} className={variant} {...props} />;
});
// After (React 19)
function Button({ variant, ref, ...props }) {
return <button ref={ref} className={variant} {...props} />;
}
Acele yok. forwardRef React 19'da çalışmaya devam eder ve React 18'i desteklemesi gereken bir kütüphane onu tutmak zorundadır, çünkü React 18 ref'i prop olarak aktarmaz. Class bileşenleri etkilenmez: bir class bileşenindeki ref hâlâ bileşen örneğini gösterir.
TypeScript
forwardRef ile tip argümanları önce ref tipi, sonra props sırasıyla gelir:
import { forwardRef } from 'react';
type FancyInputProps = { label: string };
const FancyInput = forwardRef<HTMLInputElement, FancyInputProps>(
function FancyInput({ label }, ref) {
return <input ref={ref} aria-label={label} />;
}
);
React 19'da ref'i diğer her prop gibi tiple. ComponentProps<'input'> onu zaten içerir:
import { useImperativeHandle, useRef, type ComponentProps, type Ref } from 'react';
function FancyInput(props: ComponentProps<'input'>) {
return <input {...props} />;
}
type SearchHandle = { focus: () => void; clear: () => void };
function SearchBox({ ref }: { ref?: Ref<SearchHandle> }) {
const inputRef = useRef<HTMLInputElement>(null);
useImperativeHandle(ref, () => ({
focus: () => inputRef.current?.focus(),
clear: () => {
if (inputRef.current) inputRef.current.value = '';
},
}));
return <input ref={inputRef} />;
}
// In the parent
const searchRef = useRef<SearchHandle>(null);
useRef sayfası ref'lerin kendisini anlatıyor: DOM erişimi, render etmeden kalıcı olan değerler ve ref callback'leri. Bileşenleri genel olarak tiplemek için bkz. TypeScript ile React.
Sıkça Sorulan Sorular
React'te forwardRef ne yapar?
Bir fonksiyon bileşenini, ebeveynin verdiği bir ref'in bileşene ikinci argüman olarak, (props, ref), ulaşacağı şekilde sarar. Bileşen o ref'i bir DOM düğümüne koyar, böylece ebeveyn onun üzerinde focus() gibi metotları çağırabilir.
forwardRef React 19'da kullanımdan kalktı mı?
Henüz değil ve hâlâ çalışıyor. React 19 ref'i fonksiyon bileşenlerine normal bir prop olarak aktarır, bu yüzden yeni kodun ona ihtiyacı yoktur; React ekibi de forwardRef'i gelecekteki bir sürümde kullanımdan kaldırmayı planladığını söyledi.
Özel bir bileşendeki ref'im neden null?
Bileşen ref'i aldı ama hiçbir öğeye koymadı. Onu içerideki bir DOM düğümüne bağla: <input ref={ref} />. React 19'dan önce bileşen forwardRef ile sarılmadıkça ref hiç aktarılmazdı.
useImperativeHandle ne için kullanılır?
Ebeveynin ref.current'ta gördüğü şeyi değiştirir. Tüm DOM düğümü yerine yalnızca seçtiğin metotları, örneğin focus ve clear, içeren bir nesne döndürürsün.
React 19'da class bileşenleri ref'i prop olarak alır mı?
Hayır. Bir class bileşenindeki ref hâlâ bileşen örneğini gösterir. Değişiklik yalnızca fonksiyon bileşenlerine uygulanır.