React uygulamalarında form yönetimi, kullanıcı girdilerini işlerken sıkça karşılaşılan bir konudur. Controlled ve uncontrolled bileşenler, bu girdilerin state ile nasıl ilişkilendirileceğini belirleyen iki temel yaklaşımdır. Bu yazıda her iki yöntemin farklarını, avantajlarını ve dezavantajlarını inceleyerek hangi senaryoda hangisini kullanmanız gerektiğine karar vermenize yardımcı olacağız.
Controlled Bileşen Nedir?
Controlled bileşende, form elemanının değeri React state tarafından yönetilir. Kullanıcı bir input alanına yazdığında, onChange olayı tetiklenir ve state güncellenir. Ardından state'in yeni değeri input'un value prop'una atanarak UI yeniden render edilir. Bu sayede tek bir doğruluk kaynağı (single source of truth) sağlanır.
import React, { useState } from 'react';
function ControlledForm() {
const [name, setName] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
console.log('Gönderilen isim:', name);
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<button type="submit">Gönder</button>
</form>
);
}
Avantajları
- Anlık doğrulama: Her tuş vuruşunda validasyon yapılabilir.
- Koşullu UI: State’e bağlı olarak input stilleri veya mesajları değiştirilebilir.
- Kolay test edilebilirlik: Doğrudan state değiştirerek davranışı simüle etmek mümkündür.
Dezavantajları
- Performans: Her değişiklikte yeniden render tetiklenir, büyük formlarda optimizasyon gerekebilir.
- Daha fazla kod: Her input için ayrı state ve handler yazmak zaman alabilir.
Uncontrolled Bileşen Nedir?
Uncontrolled bileşende ise form verileri DOM’un kendisi tarafından yönetilir. React, input’un değerini state’e bağlamak yerine ref aracılığıyla ihtiyaç anında DOM’dan okur. Bu yaklaşım, klasik HTML form yapısına daha yakındır ve daha az kod gerektirir.
import React, { useRef } from 'react';
function UncontrolledForm() {
const nameRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
console.log('Gönderilen isim:', nameRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" ref={nameRef} />
<button type="submit">Gönder</button>
</form>
);
}
Avantajları
- Daha hızlı basit formlar: her tuşta render olmadığı için küçük formlarda daha iyi performans.
- Daha az kod: özellikle üçüncü parti kütüphanelerle entegrasyonda kolaylık sağlar.
- React dışı kodla uyum: jQuery gibi kütüphanelerle çalışırken sorunsuzdur.
Dezavantajları
- Kısıtlı anlık kontrol: Her tuş vuruşunda validasyon yapmak zordur.
- Doğruluk kaynağı karmaşası: State ve DOM arasında senkronizasyon sorunları yaşanabilir.
Ne Zaman Hangisini Kullanmalı?
Seçim, formun karmaşıklığına ve gereksinimlere bağlıdır. Aşağıdaki tablo karar vermenize yardımcı olabilir:
| Senaryo | Önerilen Yaklaşım |
|---|---|
| Küçük, gönderim odaklı formlar (ör. arama çubuğu) | Uncontrolled |
| Gerçek zamanlı validasyon veya koşullu UI | Controlled |
| Dosya yükleme (file input) | Uncontrolled (value atanamaz) |
| İleri düzey form kütüphaneleri (Formik, React Hook Form) | Kütüphaneye bağlı (genelde controlled) |
Uncontrolled bileşenler, React dünyasında her ne kadar cazip görünse de, çoğu modern uygulama için controlled yaklaşım daha öngörülebilir ve yönetilebilirdir. Ancak formunuzda yalnızca birkaç input varsa ve gerçek zamanlı kontrole ihtiyacınız yoksa uncontrolled tercih edilebilir.
Sık Yapılan Hatalar ve Kaçınılması Gerekenler
- Controlled ve uncontrolled karıştırmak: Aynı formda bazı inputları controlled, bazılarını uncontrolled kullanmak tutarsızlığa yol açar. Mümkünse tek bir yaklaşımda karar kılın.
- Default value unutmak: Uncontrolled inputlarda
defaultValuekullanarak başlangıç değerini belirleyin; aksi halde DOM’da eski değer kalabilir. - Refs ile DOM manipülasyonunu abartmak: React’in deklaratif yapısını bozmamak için ref’leri yalnızca gerektiğinde kullanın.
Modern Form Kütüphaneleriyle Kullanım
Günümüzde React State Management Karşılaştırması yazımızda da değindiğimiz gibi, form state’ini yönetmek için Context API, Redux veya Zustand kullanılabilir. Ancak form odaklı kütüphaneler (Formik, React Hook Form) kontrollü bileşenleri temel alır ve validasyon, hata gösterme gibi işlemleri kolaylaştırır.
Eğer kendi form mantığınızı yazıyorsanız, React Custom Hooks ile State Mantığını Paylaşma yazımızdaki tekniklerle reusable bir form hook’u oluşturabilirsiniz.
Performans İpuçları
Büyük formlarda controlled bileşenlerin her tuşta yeniden render olması performans sorunu yaratabilir. Bu durumda:
- Debounce kullanarak state güncelleme sıklığını azaltın. İlgili JavaScript’te Debounce ve Throttle yazımızdan faydalanabilirsiniz.
- Input değerini sadece
onBlursırasında state’e yazmak (lazy state) alternatif bir yaklaşımdır. - React.memo ve useCallback ile gereksiz yeniden renderları engelleyin.
Sonuç
Controlled ve uncontrolled bileşenler arasındaki seçim, formun ihtiyaçlarına bağlıdır. Çoğu durumda controlled yaklaşım daha tutarlı ve test edilebilirdir, ancak uncontrolled da basit ve hızlı formlar için idealdir. Her iki yöntemi de iyi anlamak, React ile etkili form yönetiminin anahtarıdır.
Sık Sorulan Sorular
Controlled ve uncontrolled bileşen arasındaki temel fark nedir?
Controlled bileşende input değeri React state tarafından yönetilirken, uncontrolled bileşende DOM'un kendisi tarafından yönetilir. Controlled'da her değişiklik state güncellemesi tetikler, uncontrolled'da ise ref ile ihtiyaç anında değer okunur.
Hangi durumlarda uncontrolled bileşen kullanmak daha mantıklı?
Basit, gönderim odaklı formlarda (örneğin arama çubuğu veya dosya yükleme) uncontrolled bileşen daha az kod ve daha iyi performans sağlar. Ayrıca React dışı kütüphanelerle entegrasyon gerektiğinde de tercih edilebilir.
Uncontrolled bileşende input'un başlangıç değerini nasıl ayarlarım?
Uncontrolled bileşende defaultValue prop'u kullanarak başlangıç değerini belirleyebilirsiniz. value prop'u uncontrolled inputlarda kullanılmamalıdır, aksi halde react uyarı verecektir.
Controlled bileşen performans sorununa yol açar mı?
Evet, her tuş vuruşunda state güncellenip yeniden render tetiklendiği için büyük formlarda performans düşüşü olabilir. Debounce, lazy state güncelleme veya Formik/React Hook Form gibi optimize kütüphaneler kullanarak bu sorunu aşabilirsiniz.
Aynı formda hem controlled hem uncontrolled input kullanabilir miyim?
Teknik olarak mümkün olsa da önerilmez. Bu iki yaklaşımı karıştırmak state yönetimini karmaşıklaştırır ve beklenmedik hatalara yol açabilir. Mümkün olduğunca aynı formda tek bir yaklaşım kullanın.






