React 18 ve concurrent render
React 18'in eşzamanlı render modeli uygulamanın hangi davranışlarını değiştiriyor ve bu değişimi pratikte nasıl karşılamak gerekiyor.
React 18, Mart 2022’de yayımlandı. Duyuru notları okunduğunda en sık geçen terim “concurrent rendering”. Ama bu terim birçok şeyi çağrıştırabiliyor — multithreading mi, asenkron operasyonlar mı, başka bir şey mi?
Bu yazıda React 18’in render modelindeki değişimi, bunun uygulama davranışına yansımalarını ve pratikte ne yapılması gerektiğini anlatmaya çalışacağım.
Concurrent rendering ne anlama geliyor
React’in önceki sürümlerinde render işlemi synchronous ve kesintisizdi. React bir bileşen ağacını render etmeye başladığında tamamlanana kadar durmazdı. Bu, büyük güncellemelerin arayüzü donuklaştırma riskini taşıdığı anlamına geliyordu: kullanıcı bir şeye tıklıyor ama yanıt milisaniyeler yerine yüzlerce milisaniye sonra geliyor.
Concurrent rendering, render sürecini bölünebilir (interruptible) hale getiriyor. React, render işini parçalara bölüp tarayıcıya nefes alma fırsatı verebiliyor. Daha acil bir güncelleme geldiğinde (kullanıcı bir şeye tıkladı, klavyeden yazdı) React mevcut render’ı askıya alıp acil işi önce yapabiliyor.
Önemli bir not: bu asenkron JavaScript değil. JavaScript hâlâ tek iş parçacıklı (single-threaded). React kendi scheduler’ını kullanarak işin önceliğini düzenliyor; tarayıcıya aradaki boşluklarda çalışma fırsatı veriyor.
createRoot ile yeni render modu
React 18’deki değişiklikleri kullanmak için yeni root API’sine geçmek gerekiyor:
// Eski yol (React 17)
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, document.getElementById('root'));
// Yeni yol (React 18)
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
Bu tek satır değişikliği, uygulamanın concurrent özelliklere erişim kazanması için yeterli. Var olan kod büyük ölçüde çalışmaya devam ediyor.
useTransition: acil olmayan güncellemeleri işaretlemek
Concurrent rendering’in en doğrudan API’si useTransition hook’u. Bir güncellemenin “acil değil” olarak işaretlenmesini sağlıyor:
import { useState, useTransition } from 'react';
function SearchResults() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const [isPending, startTransition] = useTransition();
function handleChange(e) {
// Acil: input değerini hemen güncelle
setQuery(e.target.value);
// Acil değil: sonuçları gecikmeli güncelle
startTransition(() => {
setResults(filterResults(e.target.value));
});
}
return (
<>
<input value={query} onChange={handleChange} />
{isPending ? <span>Aranıyor...</span> : null}
<ResultList results={results} />
</>
);
}
startTransition içindeki güncelleme, daha acil güncellemeler geldiğinde ertelenebilir. Kullanıcı hızla yazdığında her harf için ağır bir liste render tetiklenmez; React bekler, yeniden render sayısını düşürür.
Otomatik batching: sessiz ama önemli değişim
React 18 ile birlikte automatic batching kapsamı genişledi. React 17’de event handler’lar içindeki birden fazla setState zaten birleştirilerek tek render üretirdi. Ama asenkron kodda (setTimeout, Promise callback) her setState ayrı render tetiklerdi.
React 18’de bu ayrım kalktı: her koşulda setState çağrıları otomatik olarak birleştiriliyor.
// React 18'de bu yalnızca tek render üretiyor
setTimeout(() => {
setCount(c => c + 1);
setName('yeni isim');
}, 1000);
Bu değişiklik çoğu uygulama için sessiz bir performans iyileştirmesi. Ama bazı kodlarda beklenmedik davranış değişikliğine yol açabilir; dikkatli olmak gerekiyor.
Geçişin pratikte maliyeti
React 18’e geçiş büyük projelerde yapılacak değişiklikler göz önüne alındığında hafif. createRoot değişikliği zorunlu; useTransition veya Suspense için yeni yazımlar opsiyonel, ihtiyaç hissedildikçe ekleniyor.
Dikkat edilmesi gereken: useEffect’in davranışı Strict Mode’da değişti. React 18 Strict Mode, efektleri kasıtlı olarak iki kez çalıştırıyor — efektlerin mount/unmount döngüsüne dayanıklı olup olmadığını test etmek için. Bazı yan etkilerin bu durumda beklenmedik biçimde davranabileceğini test ortamında görmek mümkün.
React 18, render modelini köklü biçimde değiştiriyor; ama bu değişikliği kademeli ve opt-in olarak sunuyor. Bu yaklaşım çok sayıda bileşeni olan büyük uygulamalar için doğru strateji. Her şeyi bir seferde değiştirmeye zorlamadan, hazır olanı alın, gerisini ilerleyin.