Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce bilgisayarınızda Node.js ve bir paket yöneticisinin (npm veya yarn) yüklü olması gerekir. 2026 yılı standartlarına göre Vite kullanarak hızlı bir React ortamı oluşturacağız.
Terminalinizde aşağıdaki komutları sırasıyla çalıştırarak projenizi başlatın:
# Yeni bir proje klasörü oluşturun
npm create vite@latest icerik-arama-motoru -- --template react
cd icerik-arama-motoru
npm install
npm run dev
Bu komutlar, projenizin temel dizin yapısını oluşturacak ve geliştirme sunucusunu ayağa kaldıracaktır. Tarayıcınızda 5173 portunu ziyaret ederek kurulumun başarılı olup olmadığını kontrol edebilirsiniz.
Veri Yapısını Tanımlama ve Bileşen Mimarisi
Filtreleme işleminin temelinde, üzerinde işlem yapacağımız veri seti yatar. Bu veriyi merkezi bir yerden yönetmek veya bileşenlere prop olarak geçirmek önemlidir. İlk adım olarak, arama yapacağımız içerik listesini tanımlayalım.
src/data.js adında bir dosya oluşturarak içeriklerimizi bir dizi (array) olarak tanımlayalım:
export const icerikListesi = [
{ id: 1, baslik: "React Temelleri", kategori: "Frontend" },
{ id: 2, baslik: "Node.js ile Backend", kategori: "Backend" },
{ id: 3, baslik: "CSS Grid ve Flexbox", kategori: "Tasarım" },
{ id: 4, baslik: "React Router Kullanımı", kategori: "Frontend" },
{ id: 5, baslik: "Veritabanı Güvenliği", kategori: "Backend" }
];
Bu yapı, filtreleme algoritmamız için gerekli olan temel nesne yapısını temsil eder. Her öğe bir "id" değerine sahip olmalıdır; bu, React'in liste render işlemlerinde performans için kritik olan "key" özelliğini kullanmamızı sağlar.
Arama Girişi ve State Yönetimi
Kullanıcıdan gelen girdiyi yakalamak için useState kancasını kullanacağız. Arama motorumuzun kalbi, kullanıcının yazdığı metin ile veri listesini kıyaslayan mantıktır.
import { useState } from 'react';
function AramaCubugu({ onArama }) {
return (
onArama(e.target.value)}
/>
);
}
Burada onArama fonksiyonu, üst bileşenden gelen bir "callback" (geri çağırma) fonksiyonudur. Neden doğrudan state'i burada tutmuyoruz? Çünkü arama sonucunu listeleyen ana bileşenin bu veriye ihtiyacı var. "Lifting State Up" (Durumu Yukarı Taşıma) prensibi ile veriyi en yakın ortak ataya taşıyoruz.
Filtreleme Mantığını Oluşturma
Şimdi, kullanıcının girdiği metne göre listeyi filtreleyen mantığı ana bileşenimizde (App.jsx) kuralım. filter ve toLowerCase metodları bu süreçte en büyük yardımcılarımızdır.
import { useState } from 'react';
import { icerikListesi } from './data';
function App() {
const [aramaMetni, setAramaMetni] = useState('');
const filtrelenmisIcerikler = icerikListesi.filter(item =>
item.baslik.toLowerCase().includes(aramaMetni.toLowerCase())
);
return (
);
}
Bu kod bloğu, her tuş vuruşunda filtrelenmisIcerikler dizisini yeniden hesaplar. toLowerCase() kullanımı, arama motorunuzu büyük/küçük harf duyarsız hale getirerek kullanıcı deneyimini artırır.
Liste Bileşenini Render Etme
Filtrelenmiş verileri ekrana düzgün bir şekilde yansıtmak için bir Liste bileşeni oluşturmalıyız. Bu bileşen, kendisine gelen veriyi map fonksiyonu ile işler.
function Liste({ veriler }) {
return (
{veriler.map(item => (
-
{item.baslik} - {item.kategori}
))}
);
}
Burada key özelliğine item.id atadık. Eğer key olarak index kullanırsanız, liste sıralaması değiştiğinde React'in DOM güncellemelerinde performans sorunları yaşayabilirsiniz. Her zaman benzersiz bir ID kullanmaya özen gösterin.
Performans ve Güvenlik Uyarıları
Kritik Güvenlik Uyarısı: Eğer arama motorunuz kullanıcıdan aldığı veriyi doğrudan HTML olarak render ediyorsa, XSS (Cross-Site Scripting) saldırılarına açık olabilirsiniz. React, varsayılan olarak verileri "string" olarak işler ve bu saldırıları engeller. Ancak dangerouslySetInnerHTML kullanmaktan kesinlikle kaçının.
Uygulamanız büyüdüğünde, arama işleminin her render'da yeniden hesaplanmasını engellemek için useMemo kancasını kullanabilirsiniz. Bu, büyük veri setlerinde uygulamanın donmasını engeller.
Filtreleme Yöntemleri Karşılaştırması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Client-Side (İstemci) | Hızlı, sunucu yükü yok | Büyük verilerde tarayıcıyı yorar |
| Server-Side (Sunucu) | Büyük veriler için ideal | API gecikmesi, sunucu maliyeti |
Sıkça Sorulan Sorular
Arama motoru neden büyük/küçük harf duyarlı çalışıyor?
JavaScript'in includes metodu harf duyarlıdır. Her iki tarafı da toLowerCase() ile küçük harfe çevirerek bu sorunu çözebilirsiniz.
Binlerce veriyi filtrelerken uygulama yavaşlıyor, ne yapmalıyım?
Veri setiniz çok büyükse, "Debounce" tekniğini kullanarak kullanıcının yazmayı bitirmesini beklemeli veya sunucu taraflı arama (API) yapmalısınız.
Arama sonuçları boşsa "Sonuç bulunamadı" yazısını nasıl gösteririm?
filtrelenmisIcerikler.length === 0 koşulunu kontrol ederek bir mesaj döndürebilirsiniz.
React'te arama motoru için hangi kütüphaneler önerilir?
Küçük projeler için kendi yazdığınız mantık yeterlidir. Ancak kompleks arama, sıralama ve sayfalama için TanStack Table gibi kütüphaneleri inceleyebilirsiniz.
Arama motoru SEO uyumlu mu?
İstemci taraflı (client-side) filtreleme, arama motoru botları için içeriği hemen indekslemeyebilir. SEO kritikse Next.js gibi çerçevelerle sunucu taraflı render (SSR) kullanmalısınız.
Debounce Mekanizması ile Performans Optimizasyonu
Kullanıcı arama kutusuna her karakter girdiğinde filtreleme fonksiyonunun tetiklenmesi, özellikle büyük veri setlerinde gereksiz işlem yükü oluşturur. Bu durumu engellemek için Debounce (gecikmeli tetikleme) tekniğini kullanmalıyız. Bu yöntem, kullanıcının yazmayı bırakmasını belirli bir süre bekler ve ardından filtrelemeyi başlatır.
Aşağıdaki örnekte, lodash.debounce kütüphanesini kullanmadan, saf JavaScript ile bir debounce mantığını nasıl entegre edeceğinizi görebilirsiniz:
import { useState, useCallback, useMemo } from 'react';
const useDebounce = (callback, delay) => {
const memoizedCallback = useCallback(callback, []);
return useMemo(() => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => memoizedCallback(...args), delay);
};
}, [memoizedCallback, delay]);
};
// Bileşen içerisinde kullanımı:
const handleSearch = useDebounce((value) => {
setSearchTerm(value);
}, 500);
Filtreleme İşlemlerinde Birim Testleri
Arama motorunuzun kararlılığını sağlamak için mantıksal testler yazmak kritiktir. Özellikle filter fonksiyonunuzun boş veri, özel karakterler veya büyük/küçük harf duyarlılığı gibi durumlarda nasıl tepki verdiğini doğrulamalısınız. Jest ve React Testing Library kullanarak filtreleme mantığınızı şu şekilde test edebilirsiniz:
import { filterData } from './utils/filterLogic';
test('arama terimi ile eşleşen verileri döndürür', () => {
const data = [{ title: 'React Rehberi' }, { title: 'Vue İpuçları' }];
const result = filterData(data, 'React');
expect(result).toHaveLength(1);
expect(result[0].title).toBe('React Rehberi');
});
test('eşleşme olmadığında boş dizi döndürür', () => {
const data = [{ title: 'React Rehberi' }];
const result = filterData(data, 'Angular');
expect(result).toEqual([]);
});
Test Stratejileri
- İzole Testler: Filtreleme fonksiyonunu bileşenden ayırarak saf bir fonksiyon (pure function) haline getirin ve bağımsız test edin.
- Edge Case Testleri: Kullanıcı boşluk karakteri girdiğinde veya veritabanından
nulldeğer geldiğinde uygulamanın çökmediğinden emin olun. - Entegrasyon Testleri: Arama kutusuna girilen değerin, liste bileşeninde doğru sayıda DOM elemanı oluşturup oluşturmadığını kontrol edin.
Uygulama İçin İleri Düzey İpuçları
Arama motorunuzu daha profesyonel bir seviyeye taşımak için şu stratejileri değerlendirebilirsiniz:
- Highlighting (Vurgulama): Arama sonuçlarında eşleşen metin parçalarını
etiketi ile işaretleyerek kullanıcı deneyimini iyileştirin. - URL Parametreleri: Arama terimini
window.location.search(query string) içerisine ekleyerek, kullanıcının yaptığı aramayı paylaşılabilir bir link haline getirin. - Web Workers: Veri setiniz 50.000 satırı aşıyorsa, filtreleme işlemini ana thread'i dondurmamak için Web Workers üzerinde arka planda çalıştırın.
Sonuç
React ile bileşen bazlı bir içerik filtreleme arama motoru oluşturmak, uygulamanızın kullanıcı etkileşimini ciddi oranda artırır. Bu rehberde, veri yönetiminden bileşen mimarisine kadar temel adımları tamamladık. Bir sonraki adım olarak, arama kutusuna "debounce" mekanizması ekleyerek performans optimizasyonunu derinleştirebilirsiniz.
Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce girdi sanitizasyonu ve veri doğrulama işlemlerini uyguladığınızdan emin olun.

Yorumlar (0)
Yorum Yaz