Kategori Filtreleriyle Sabit A-Z Sıralamayı Aynı Anda Yönetmek
/projects sayfasında iki bağımsız state var: hangi kategori seçili, hangi sayfadayız. İkisi birbirini kırmadan çalışması gereken basit ama kolayca yanlış yapılabilecek bir etkileşim.
const [category, setCategory] = useState<ProjectCategory | undefined>(undefined);
const [page, setPage] = useState(1);
const { data, isLoading, isError } = useProjects({ page, pageSize: PAGE_SIZE, category });
function changeCategory(next: ProjectCategory | undefined) {
setCategory(next);
setPage(1);
}
Kritik satır: changeCategory her zaman sayfayı sıfırlıyor
Kategori değiştiğinde page'i 1'e resetlemezsen, kullanıcı "e-ticaret" kategorisinin 3. sayfasındayken "demo" kategorisine geçtiğinde API'ye page=3&category=demo gider — ama demo kategorisinde 3 sayfa yoksa boş bir liste görünür, kullanıcı "burada hiç proje yok" sanır. changeCategory fonksiyonunun setPage(1)'i de içermesi, bu iki state'in birbirine bağımlı olduğunu tek bir çağrı noktasında garanti ediyor — her kategori butonuna ayrı ayrı "ve sayfayı sıfırla" yazmak yerine.
Sayaçlar neden aktif filtreden bağımsız
const totalCount = data
? Object.values(data.categoryCounts).reduce((sum, n) => sum + n, 0)
: undefined;
categoryCounts API'den tüm katalog üzerinden hesaplanmış geliyor (bkz. groupBy — aktif where filtresinden bağımsız). Bu sayede kullanıcı "e-ticaret" sekmesindeyken "demo" sekmesinin yanındaki sayı da doğru kalıyor — her sekmenin sayısı, o an aktif olan filtreye göre değil, tüm katalog üzerinden hesaplanıyor.
Neden URL query param değil, component state
Sayfa/kategori state'i useState içinde tutuluyor, URL'e yazılmıyor. Bilinçli bir basitlik tercihi: bu ölçekte (kişisel portföy, SEO açısından /projects sayfasının kendisi zaten indexleniyor, alt-durumlarının değil) geri/ileri navigasyonunda filtre durumunu korumanın getirisi, useSearchParams + router.push senkronizasyonunun getirdiği karmaşıklığa değmiyor. Bu tradeoff, daha büyük bir sitede (çok sayfalı ürün kataloğu, paylaşılabilir filtre linkleri gerektiren bir e-ticaret) tersine dönerdi.