React İle Filtrelenebilir Bir Arama Bileşeni Nasıl Yapılır?

React İle Filtrelenebilir Bir Arama Bileşeni Nasıl Yapılır?
React İle Filtrelenebilir Bir Arama Bileşeni Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Projeye başlamadan önce bilgisayarınızda Node.js'in güncel bir sürümünün (LTS) kurulu olduğundan emin olmalısınız. React projenizi oluşturmak için Vite gibi modern ve hızlı bir araç kullanmanızı öneririm. Aşağıdaki komutlar, projenizi kurmak ve gerekli bağımlılıkları yüklemek için standart yöntemdir.

# Yeni bir React projesi oluşturun
npm create vite@latest arama-uygulamasi -- --template react
cd arama-uygulamasi
npm install
npm run dev

Bu adımlar sonrasında tarayıcınızda 5173 portunda çalışan boş bir React projesi göreceksiniz. Projenin dosya yapısını temizleyerek components adında bir klasör oluşturun ve içerisine SearchFilter.jsx dosyasını ekleyerek işe başlayın.

Veri Setini Hazırlama ve State Yönetimi

Filtreleme işlemi için öncelikle üzerinde işlem yapacağımız bir veri setine ihtiyacımız var. Genellikle bu veriler bir API'den gelir, ancak başlangıç aşamasında yerel bir dizi (array) ile çalışacağız. React'te useState kancası, kullanıcının arama kutusuna girdiği metni tutmak için kullanılır.

import { useState } from 'react';

const veriler = [
  { id: 1, isim: 'React Eğitimi' },
  { id: 2, isim: 'JavaScript Temelleri' },
  { id: 3, isim: 'CSS ile Tasarım' },
  { id: 4, isim: 'Node.js Backend' }
];

export default function SearchFilter() {
  const [aramaMetni, setAramaMetni] = useState('');
  // ...
}

Burada aramaMetni değişkeni, kullanıcının klavyeden girdiği her karakteri anlık olarak yakalar. setAramaMetni ise bu değeri güncelleyerek bileşenin yeniden render edilmesini (ekranın güncellenmesini) sağlar.

Filtreleme Mantığını Adım Adım Oluşturma

Filtreleme mantığı, ana dizimiz üzerinde filter metodunun kullanılmasıyla gerçekleşir. Kullanıcının girdiği metin ile veri setimizdeki öğeleri karşılaştıracağız. Büyük/küçük harf duyarlılığını ortadan kaldırmak için her iki tarafı da toLowerCase() metodundan geçirmek kritik bir öneme sahiptir.

const filtrelenmisVeriler = veriler.filter((ogrenim) =>
  ogrenim.isim.toLowerCase().includes(aramaMetni.toLowerCase())
);

Bu kod bloğu, aramaMetni her değiştiğinde çalışır. includes metodu, girilen karakter dizisinin öğe içerisinde geçip geçmediğini kontrol eder. Eğer kullanıcı hiçbir şey yazmadıysa, includes('') her zaman true döneceğinden tüm liste ekranda görünür.

Arama Bileşenini Kullanıcı Arayüzüne Entegre Etme

Şimdi bu mantığı JSX yapısına dökelim. Kullanıcıdan veri alacağımız bir input etiketi ve filtrelenmiş sonuçları göstereceğimiz bir ul listesi oluşturacağız. React'te kontrollü bileşen (controlled component) yaklaşımını kullanarak input değerini aramaMetni state'ine bağlıyoruz.

return (
  
setAramaMetni(e.target.value)} />
    {filtrelenmisVeriler.map((ogrenim) => (
  • {ogrenim.isim}
  • ))}
);

Burada dikkat edilmesi gereken en önemli nokta key kullanımıdır. React, liste elemanlarını birbirinden ayırt edebilmek için benzersiz bir anahtar bekler. Veri setinizdeki id değerini kullanmak, performans ve hata yönetimi açısından en doğru yaklaşımdır.

Performans İpuçları ve UseMemo Kullanımı

Veri setiniz büyüdüğünde, her karakter girişinde tüm filtreleme işleminin tekrar hesaplanması performans sorunlarına yol açabilir. Bu noktada useMemo kancası devreye girer. useMemo, hesaplama sonucunu önbelleğe alır ve yalnızca bağımlılıklar (burada aramaMetni) değiştiğinde tekrar hesaplama yapar.

import { useState, useMemo } from 'react';

const filtrelenmisVeriler = useMemo(() => {
  return veriler.filter((ogrenim) =>
    ogrenim.isim.toLowerCase().includes(aramaMetni.toLowerCase())
  );
}, [aramaMetni]);

Bu yöntem, gereksiz hesaplamaları engelleyerek uygulamanızın daha akıcı çalışmasını sağlar. Özellikle binlerce satırlık veri ile çalışıyorsanız, useMemo kullanımı bir tercih değil, zorunluluk haline gelir.

Karşılaştırma: Filtreleme Yöntemleri

Yöntem Avantajı Dezavantajı
Basit Filter Kolay uygulanır, küçük veriler için hızlıdır. Büyük verilerde render performansını düşürür.
useMemo + Filter Yüksek performans, gereksiz hesaplama yapmaz. Bellek kullanımı biraz daha fazladır.
Debounce + API Sunucu yükünü azaltır, gerçek zamanlı arama sağlar. Karmaşık yapı, ek kütüphane gerektirebilir.

Güvenlik Uyarısı: Eğer arama sonuçlarını doğrudan kullanıcıdan gelen veriyle bir HTML içeriğine dönüştürüyorsanız, XSS (Cross-Site Scripting) saldırılarına karşı dikkatli olun. React, varsayılan olarak verileri "escape" ederek (güvenli hale getirerek) bu saldırıları engeller. Ancak dangerouslySetInnerHTML kullanımından kesinlikle kaçının.

Sıkça Sorulan Sorular

Arama sonucunda veri bulunamazsa ne yapmalıyım?

Filtrelenmiş dizinin uzunluğunu kontrol ederek kullanıcıya "Sonuç bulunamadı" gibi bir mesaj gösterebilirsiniz. {filtrelenmisVeriler.length === 0 &&

Sonuç yok

} yapısını kullanmak oldukça pratiktir.

Büyük/küçük harf duyarlılığını nasıl tamamen kaldırırım?

Hem arama metnini hem de karşılaştırılan veriyi .toLowerCase() veya .toLocaleLowerCase('tr-TR') fonksiyonlarından geçirerek Türkçe karakter sorunlarını da çözebilirsiniz.

API'den gelen verilerde arama nasıl yapılır?

Veriyi useEffect kancası ile fetch veya axios kullanarak çekmeli, ardından useState içerisinde saklayarak filtreleme işlemini aynı mantıkla yapmalısınız.

Debounce nedir, neden kullanmalıyım?

Debounce, kullanıcının yazmayı bitirmesini bekleyerek filtreleme işlemini tetikleyen bir tekniktir. Özellikle API isteklerinde, her harf basımında sunucuya istek gitmesini engellemek için kullanılır.

Filtrelemeyi birden fazla kritere göre yapabilir miyim?

Evet, filter fonksiyonu içerisine || (veya) operatörünü ekleyerek hem isim hem de kategori gibi farklı alanlarda arama yapacak şekilde mantığı genişletebilirsiniz.

Gelişmiş Arama Deneyimi İçin Test Stratejileri

Filtreleme mekanizmanızın karmaşıklığı arttıkça, kullanıcı deneyimini korumak için test süreçlerini otomatize etmek kritik bir hal alır. Özellikle uç durumları (edge cases) ele almak, uygulamanızın beklenmedik girdiler karşısında çökmesini engeller.

Birim Testlerinde Filtreleme Mantığını Doğrulama

Filtreleme fonksiyonunuzu bileşenden bağımsız bir yardımcı fonksiyon (utility function) olarak dışarı çıkarmak, test edilebilirliği artırır. Jest ve React Testing Library kullanarak, arama sonucunun doğruluğunu şu şekilde test edebilirsiniz:

// filterUtils.test.js
import { filterData } from './filterUtils';

const mockData = [{ id: 1, name: 'React' }, { id: 2, name: 'Vue' }];

test('arama terimi ile doğru veriyi döndürür', () => {
  const result = filterData(mockData, 'Re');
  expect(result).toHaveLength(1);
  expect(result[0].name).toBe('React');
});

test('boş arama terimi tüm veriyi döndürür', () => {
  const result = filterData(mockData, '');
  expect(result).toHaveLength(2);
});

Arama Bileşenini Alternatif Kütüphanelerle Güçlendirme

Kendi filtreleme mantığınızı yazmak öğrenme süreci için harika olsa da, büyük ölçekli ve karmaşık veri setlerinde (binlerce kayıt gibi) profesyonel kütüphaneler kullanmak performansı optimize edebilir. Fuse.js gibi kütüphaneler, "fuzzy search" (bulanık arama) desteği sunarak kullanıcıların yazım hatalarına karşı daha toleranslı arama sonuçları almasını sağlar.

Fuse.js ile Bulanık Arama Entegrasyonu

Bulanık arama, kullanıcının "Reat" yazdığında bile "React" sonucunu görmesini sağlar. İşte basit bir entegrasyon örneği:

import Fuse from 'fuse.js';
import { useMemo } from 'react';

const useFuzzySearch = (data, query) => {
  const fuse = useMemo(() => new Fuse(data, {
    keys: ['name', 'category'],
    threshold: 0.3 // 0 ile 1 arası, düşük değer daha katı eşleşme sağlar
  }), [data]);

  return useMemo(() => {
    if (!query) return data;
    return fuse.search(query).map(result => result.item);
  }, [fuse, query, data]);
};
İpucu: Kütüphane kullanırken paket boyutunu (bundle size) göz önünde bulundurun. Eğer sadece basit bir metin eşleşmesi yapıyorsanız, JavaScript'in yerel includes() metodu en hızlı ve en hafif çözümdür.

Büyük Veri Setlerinde Performans Optimizasyonu

Veri setiniz 5.000 satırı aştığında, her tuş vuruşunda (keystroke) filtreleme yapmak ana iş parçacığını (main thread) kilitleyebilir. Bu durumu aşmak için "Virtualization" (Sanal Liste) tekniklerini kullanmalısınız.

  • React Window veya React Virtualized: Sadece ekranda görünen öğeleri DOM'a basarak bellek kullanımını minimuma indirir.
  • Web Workers: Çok ağır filtreleme işlemlerini ana thread dışına taşıyarak arayüzün donmasını engeller.
  • Memoization: useMemo kullanarak hesaplama maliyetli filtreleme işlemlerini önbelleğe alın.

Bu stratejileri uygulayarak, uygulamanızın hem küçük hem de büyük ölçekli verilerde aynı akıcılıkta çalışmasını sağlayabilirsiniz. Unutmayın, en iyi arama deneyimi, kullanıcının ne aradığını tahmin eden ve bunu milisaniyeler içinde sunan deneyimdir.

Sonuç

React ile filtrelenebilir bir arama bileşeni oluşturmak, bileşen yaşam döngüsü ve state yönetimi konularında size önemli bir tecrübe kazandıracaktır. Bu rehberde öğrendiğiniz useState, useMemo ve filter kombinasyonu, hemen hemen her React projesinde karşınıza çıkacak temel bir kalıptır.

Bir sonraki adım olarak, bu bileşeni daha da geliştirerek "debounce" mekanizmasını ekleyebilir veya verileri bir dış API'den çekerek gerçek dünya senaryolarına taşıyabilirsiniz. Kod yazarken her zaman temiz kod prensiplerine sadık kalmayı ve bileşenlerinizi küçük, yönetilebilir parçalara bölmeyi unutmayın.

Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanırken veri doğrulama ve güvenlik önlemlerini (input sanitization) projenizin ihtiyaçlarına göre özelleştirmeniz gerektiğini unutmayın.

Bu yazıya tepkinizi paylaşın:
Zeynep Arslan

Mutfak pratikleri ve ev düzeni konularında yıllardır içerik üretiyorum. Okuyuculara zaman kazandıran, uygulanabilir ve sürdürülebilir yaşam tarzı önerileri sunuyorum.

Yorumlar (0)

Yorum Yaz