React'te ref kullanarak DOM elemanlarına veya sınıf bileşenlerine doğrudan erişebilirsiniz. Peki ya fonksiyonel bir alt bileşenin DOM'una veya iç metodlarına erişmeniz gerekiyorsa? İşte bu noktada forwardRef ve useImperativeHandle devreye girer. Bu yazıda, ref'leri alt bileşenlere nasıl aktaracağınızı ve alt bileşenin belirli metodlarını üst bileşene nasıl açacağınızı adım adım inceleyeceğiz.
forwardRef Nedir ve Ne Zaman Kullanılır?
forwardRef, bir bileşenin ref prop'unu altındaki bir DOM elemanına veya başka bir bileşene iletmesini sağlayan bir React API'sidir. Normalde fonksiyonel bileşenler ref alamaz; forwardRef bu kısıtlamayı kaldırır. Yaygın kullanım alanları:
- Özel bir input bileşenine focus vermek
- Bir animasyon kütüphanesiyle DOM'a erişmek
- Üçüncü taraf bir kütüphaneye alt bileşenin DOM'unu iletmek
Temel Kullanım: forwardRef ile Ref Aktarma
Aşağıdaki örnekte, CustomInput adlı bir bileşen, forwardRef kullanarak aldığı ref'i bir input elemanına aktarıyor:
import React, { forwardRef } from 'react';
const CustomInput = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
// Üst bileşen:
const Parent = () => {
const inputRef = useRef(null);
const handleClick = () => inputRef.current.focus();
return (
<>
<CustomInput ref={inputRef} />
<button onClick={handleClick}>Focusla</button>
</>
);
};
Bu sayede Parent, CustomInput'ın içindeki input'a doğrudan erişebilir ve focus verebilir.
useImperativeHandle ile Metotları Dışa Açma
Bazen alt bileşenin tüm DOM'u yerine yalnızca belirli metodlarını (örneğin focus, reset, validate) dışa açmak isteyebilirsiniz. useImperativeHandle bu işe yarar. Şöyle kullanılır:
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
const CustomInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
reset: () => { inputRef.current.value = ''; },
getValue: () => inputRef.current.value
}));
return <input ref={inputRef} {...props} />;
});
// Kullanımı:
const Parent = () => {
const inputRef = useRef();
const handleReset = () => inputRef.current.reset();
const handleGetValue = () => alert(inputRef.current.getValue());
return (
<>
<CustomInput ref={inputRef} />
<button onClick={handleReset}>Sıfırla</button>
<button onClick={handleGetValue}>Değeri Göster</button>
</>
);
};
Burada useImperativeHandle, ref'e üç metod ekler: focus, reset ve getValue. Üst bileşen yalnızca bu metodlara erişebilir, doğrudan input'a erişemez.
Sık Yapılan Hatalar ve Dikkat Edilmesi Gerekenler
- İhtiyaç olmayan yerde kullanmak: Çoğu durumda state lifting veya callback ile sorunu çözebilirsiniz. Ref kullanımı, DOM erişimi veya zorunlu metod çağrıları için saklanmalıdır. Aksi halde kodunuzu daha karmaşık hale getirir.
- ForwardRef'te ref parametresini unutmak:
forwardRefalan bileşenin ikinci parametresiref'tir. Bunu kullanmazsanız ref aktarılmaz. - UseImperativeHandle'ta gereksiz bağımlılıklar:
useImperativeHandle'ın ikinci argümanı bir fonksiyondur ve döndürdüğü nesne her render'da yeniden oluşturulur. Eğer bağımlılıkları (dependencies) doğru ayarlamazsanız, referans kararlılığı bozulabilir. Boş dizi ([]) vererek metodların sabit kalmasını sağlayın. - Birden fazla ref aktarımı: Bir bileşende birden fazla alt DOM'a ref aktarmanız gerekiyorsa, her biri için ayrı ref oluşturun ve
useImperativeHandleile toplu olarak dışa açın.
Performans ve Ölçeklenebilirlik İpuçları
forwardRef ve useImperativeHandle kullanırken, metodların her render'da yeniden oluşturulmasını önlemek için useCallback veya useMemo kullanabilirsiniz. Ancak çoğu durumda useImperativeHandle'ın bağımlılık dizisini boş bırakmak yeterlidir. Daha karmaşık state yönetimi gerekiyorsa, React'teki custom hook yaklaşımlarını inceleyebilirsiniz.
Eğer projenizde çok sayıda alt bileşen ve ref aktarımı varsa, state management kütüphaneleriyle prop drilling sorununu çözmek daha uygun olabilir. Ref'leri yalnızca gerçekten DOM erişimi gerektiğinde kullanın.
Alternatif Yaklaşımlar: Ne Zaman Ref Kullanmamalısınız?
Ref kullanımı React'in deklaratif doğasına aykırıdır. Mümkün olduğunca state ve prop'larla iletişim kurmaya çalışın. Örneğin, bir bileşenin fokuslanması gerekiyorsa, bir state değişkeniyle kontrol edebilirsiniz. Ancak bazen (örneğin bir üçüncü taraf kütüphane entegrasyonu) imperatif yaklaşım kaçınılmazdır. Bu durumlarda forwardRef ve useImperativeHandle temiz bir çözüm sunar.
SSS
Sıkça sorulan soruları aşağıda bulabilirsiniz.
Sık Sorulan Sorular
forwardRef ile ref aktarmak neden gereklidir?
Fonksiyonel bileşenler varsayılan olarak ref almaz. forwardRef, bir bileşenin ref prop'unu alt DOM elemanına veya başka bir bileşene iletmesini sağlayarak bu kısıtlamayı kaldırır.
useImperativeHandle hangi durumlarda kullanılmalıdır?
Bir alt bileşenin belirli metodlarını (focus, reset, validate gibi) üst bileşene açmak istediğinizde, ancak tüm DOM'u göstermek istemediğinizde kullanılır.
forwardRef ile ref aktarırken performans sorunu oluşur mu?
Hayır, forwardRef sadece bir ref iletim mekanizmasıdır. Performans etkisi ihmal edilebilir düzeydedir. Ancak useImperativeHandle içinde bağımlılıkları doğru yönetmezseniz gereksiz render'lara neden olabilir.
Bir bileşende birden fazla DOM elemanına ref aktarmak mümkün mü?
Evet, her bir alt eleman için ayrı ref oluşturup useImperativeHandle ile bu ref'leri bir nesne olarak dışa açabilirsiniz.






