Gereksinimler ve Ön Hazırlık
Uygulamaya başlamadan önce sisteminizde Node.js (v20 veya üzeri) yüklü olmalıdır. React projelerimizde güncel performans ölçümleri için Vite kullanacağız. Sanallaştırma işlemleri için sektör standardı olan react-window kütüphanesini tercih edeceğiz.
Projenizi başlatmak için terminalinizde aşağıdaki komutları çalıştırın:
npm create vite@latest liste-sanallastirma -- --template react
cd liste-sanallastirma
npm install react-window lodash
Bu adımlar, projenin temel yapısını kurar ve sanallaştırma için gerekli olan react-window kütüphanesini bağımlılıklarınıza ekler. lodash kütüphanesini ise büyük veri setlerini hızlıca oluşturmak için kullanacağız.
Adım 1: Büyük Veri Seti Oluşturma
Performans testleri yapabilmek için 10.000 öğelik bir liste verisine ihtiyacımız var. Bu veriyi uygulamanın başında oluşturarak, sanallaştırmanın etkisini net bir şekilde gözlemleyebiliriz.
import { range } from 'lodash';
const VERI_SETI = range(10000).map((index) => ({
id: index,
baslik: `Öğe Numarası: ${index + 1}`,
aciklama: `Bu, ${index + 1}. öğenin detaylı açıklamasıdır.`
}));
Bu kod bloğu, 10.000 elemanlı bir dizi oluşturur. Eğer bu veriyi doğrudan bir map fonksiyonu ile DOM'a basmaya çalışsaydınız, React'in "reconciliation" (uzlaştırma) süreci ciddi bir gecikme yaşatırdı.
Adım 2: Temel Liste Sanallaştırma Uygulaması
react-window kullanarak FixedSizeList bileşenini projemize dahil ediyoruz. Bu bileşen, liste öğelerinin yüksekliklerinin sabit olduğu durumlarda en yüksek performansı sağlar.
import { FixedSizeList as List } from 'react-window';
const ListeBileseni = () => (
{({ index, style }) => (
{VERI_SETI[index].baslik}
)}
);
Burada height, listenin görünebilir alanını; itemSize ise her bir satırın piksel cinsinden yüksekliğini belirler. react-window, sadece görünen alandaki (viewport) öğeleri render eder.
Adım 3: Performans Karşılaştırması ve Yöntemler
Liste sanallaştırmanın geleneksel yöntemlere göre avantajlarını anlamak için aşağıdaki tabloyu inceleyebilirsiniz.
| Yöntem | Bellek Kullanımı | Render Hızı | Kullanım Alanı |
|---|---|---|---|
| Standart Map | Çok Yüksek | Yavaş | < 100 öğe |
| Sanallaştırma | Düşük | Çok Hızlı | > 500 öğe |
Kritik Uyarı: Sanallaştırma kullanırken, liste öğelerinizin CSS
position: absoluteile konumlandırıldığını unutmayın. Eğer öğelerinizde karmaşık CSS grid veya flex yapıları varsa,styleprop'unu mutlaka öğenize uyguladığınızdan emin olun.
Adım 4: Değişken Yükseklikli Öğeler (VariableSizeList)
Gerçek dünya uygulamalarında her liste öğesinin yüksekliği aynı olmayabilir. Bu durumda VariableSizeList kullanmanız gerekir. Her öğenin yüksekliğini dinamik olarak hesaplayan bir fonksiyon tanımlarız.
import { VariableSizeList as List } from 'react-window';
const getItemSize = index => (index % 2 === 0 ? 50 : 100);
const DegiskenListe = () => (
{({ index, style }) => {index}. Öğe}
);
Bu yöntem, farklı boyutlardaki içerikleri yönetirken uygulamanın akıcılığını korur. getItemSize fonksiyonu, performans için memoize (önbelleğe alma) edilmelidir.
Adım 5: Güvenlik ve Hata Yönetimi
Büyük listelerle çalışırken, API'den gelen verilerin XSS (Cross-Site Scripting) saldırılarına karşı temizlenmesi hayati önem taşır. Kullanıcı girdilerini veya dış kaynaklı verileri asla doğrudan dangerouslySetInnerHTML ile render etmeyin.
// Güvenli veri render etme örneği
const GuvenliOge = ({ veri }) => (
{veri.baslik.replace(/]*>/g, '')}
);
Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) verilerin doğrulanması ve sanitizer kütüphaneleri (örneğin: DOMPurify) kullanılması geliştiricinin sorumluluğundadır.
Adım 6: Debug İpuçları ve Yaygın Hatalar
Sanallaştırma sırasında karşılaşılan en yaygın hata, listenin boş görünmesi veya öğelerin üst üste binmesidir. Genellikle style prop'unun öğeye atanmaması veya kapsayıcı div elemanının yüksekliğinin tanımlanmaması buna neden olur.
Tarayıcı geliştirici araçlarında "Paint Flashing" özelliğini açarak, sadece görünen öğelerin yeniden boyandığını (repaint) doğrulayabilirsiniz. Eğer tüm liste aynı anda boyanıyorsa, sanallaştırma düzgün çalışmıyor demektir.
Sıkça Sorulan Sorular
Sanallaştırma SEO'yu etkiler mi?
Evet, eğer içeriğiniz arama motorları tarafından taranması gereken bir metin ise, sanallaştırma DOM'dan öğeleri sildiği için arama motorları bu öğeleri göremeyebilir. Bu teknik daha çok kullanıcı panelleri ve özel uygulamalar için önerilir.
Mobil cihazlarda sanallaştırma gerekli mi?
Mobil cihazlar bellek konusunda masaüstü bilgisayarlara göre daha kısıtlıdır. Bu nedenle, mobil uygulamalarda sanallaştırma kullanmak, uygulamanın çökmesini önlemek için bir zorunluluktur.
React.memo ile birlikte kullanılmalı mı?
Evet, liste öğelerini React.memo ile sarmalamak, liste kaydırılırken her bir öğenin gereksiz yere tekrar render edilmesini engeller ve performansı artırır.
Infinite Scroll ile farkı nedir?
Infinite Scroll, veriyi parça parça yükler; sanallaştırma ise yüklenen verinin sadece bir kısmını ekranda gösterir. İkisi genellikle birlikte kullanılır.
Hangi kütüphane daha iyi: react-window mu react-virtualized mi?
react-window, react-virtualized kütüphanesinin daha hafif ve modern bir halidir. Yeni projelerde react-window tercih etmeniz önerilir.
İleri Seviye Optimizasyon: Grid Sanallaştırma
Liste sanallaştırmasının ötesine geçerek, iki boyutlu veri tablolarında veya galeri görünümlerinde FixedSizeGrid bileşenini kullanabilirsiniz. Bu yöntem, özellikle Excel benzeri veri tabloları veya fotoğraf galerileri gibi geniş veri setlerinde DOM düğümlerini minimumda tutmanıza olanak tanır.
Grid Yapısında Performans Yönetimi
Grid yapısında her hücrenin kendi render döngüsü vardır. Bu nedenle, columnWidth ve rowHeight değerlerinin sabit tutulması, hesaplama maliyetini düşürür. Aşağıda, 1000x1000'lik bir grid yapısının temel kurulum örneği yer almaktadır:
import { FixedSizeGrid as Grid } from 'react-window';
const Cell = ({ columnIndex, rowIndex, style }) => (
Hücre {rowIndex},{columnIndex}
);
const App = () => (
{Cell}
);
Sanallaştırılmış Listeler İçin Birim Testi Stratejileri
Sanallaştırılmış bileşenleri test ederken dikkat edilmesi gereken en önemli nokta, DOM'un sadece o an görünür olan öğeleri içermesidir. Geleneksel getByText sorguları, liste dışındaki öğeler için başarısız olacaktır. Bu durumda, kaydırma (scroll) simülasyonu yapmanız gerekir.
Test Ortamında Kaydırma Simülasyonu
Testlerinizde react-testing-library kullanıyorsanız, scrollTo metodunu manuel olarak tetikleyerek sanallaştırılmış öğelerin render edilip edilmediğini kontrol edebilirsiniz:
import { render, fireEvent } from '@testing-library/react';
test('kaydırma yapıldığında yeni öğeler render edilmeli', () => {
const { getByTestId } = render();
const listContainer = getByTestId('list-container');
// Kaydırma olayını tetikle
fireEvent.scroll(listContainer, { target: { scrollTop: 500 } });
// Görünür olması beklenen öğeyi kontrol et
expect(getByTestId('item-20')).toBeInTheDocument();
});
İpucu: Sanallaştırma kütüphaneleri genelliklecontainerelementine birrefatamanızı gerektirir. Testlerinizde burefüzerindenscrollTopdeğerini manipüle etmek, gerçek kullanıcı davranışını en iyi simüle eden yöntemdir.
Alternatif Kütüphane: TanStack Virtual
Eğer projenizde daha fazla esneklik ve TypeScript desteği arıyorsanız, react-window yerine @tanstack/react-virtual kullanmayı düşünebilirsiniz. Bu kütüphane, "headless" yapısı sayesinde DOM yapısı üzerinde tam kontrol sağlar ve değişken boyutlu öğeleri çok daha performanslı yönetir.
- Daha küçük paket boyutu: Sadece ihtiyacınız olan fonksiyonları import edebilirsiniz.
- Esnek DOM yapısı: Kendi HTML etiketlerinizi ve CSS sınıflarınızı kullanmanıza izin verir.
- Gelişmiş API:
scrollToIndexgibi karmaşık navigasyon işlemleri için yerleşik destek sunar.
Özetle, basit listeler için react-window yeterli olsa da, karmaşık ve yüksek etkileşimli arayüzlerde TanStack Virtual modern bir standart haline gelmiştir.
Sonuç
React ile performanslı liste sanallaştırma, büyük veri kümelerini yönetmek için vazgeçilmez bir yetenektir. Bu rehberde öğrendiğiniz FixedSizeList ve VariableSizeList yapılarını kullanarak, kullanıcılarınıza akıcı ve hızlı bir deneyim sunabilirsiniz. Bir sonraki adım olarak, bu listeleri API'den gelen verilerle birleştiren "Infinite Loading" (Sonsuz Kaydırma) mantığını entegre etmeyi deneyebilirsiniz.


Yorumlar (0)
Yorum Yaz