perf: harita/tablo re-render'ları + content-visibility (Faz 6)
- tercih-haritasi: viewBox animasyonu transient — kare başına setState (380ms × ~23 render × 81 path) yerine svg.setAttribute; il path ref callback'leri key başına stabil; il özetleri/şerit/pin grupları useMemo; reduce×3+baskinRisk tek geçiş; çift lookup ve çift uniLogoYoluFromAd kalktı - liste-store: O(1) idSet + useListedeMi/useListeDoluMu primitive selector'ları; program-ekle-butonu artık tüm listeye abone değil — 50 satırlık tabloda mutasyon başına 50 yerine yalnız değişen buton render olur - bolum-program-listesi: decorate-sort-undecorate yerine stable toSorted; sıralama/sayfalama startTransition'da - il-secim-haritasi: normalizeIlAdi modül seviyesinde precompute (render başına ~1000 string normalizasyonu vardı); Map/Set/sort useMemo - kt-cv-satir utility: uzun tablo satırlarında content-visibility:auto + contain-intrinsic-size (program/bolum/universite/rapor tabloları) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
// il seçilen Türkiye haritası. Mavi ton ildeki program sayısını, turuncu
|
||||
// kontur seçimi gösterir. KKTC gibi harita dışı yerler çip olarak eklenir.
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { cities } from "turkey-map-react/lib/data";
|
||||
import {
|
||||
HARITA_GENISLIK,
|
||||
@@ -12,6 +13,14 @@ import {
|
||||
normalizeIlAdi,
|
||||
} from "@/lib/harita";
|
||||
|
||||
// normalizeIlAdi (3 replace + toLocaleUpperCase) modül yükünde İL BAŞINA BİR
|
||||
// kez koşar; eskiden her render'da sort comparator içinde ~1000 kez
|
||||
// çağrılıyordu (81 il × ~çift log n karşılaştırma × 2 çağrı).
|
||||
const NORMAL_SEHIRLER = cities.map((city) => ({
|
||||
city,
|
||||
key: normalizeIlAdi(city.name),
|
||||
}));
|
||||
|
||||
export function IlSecimHaritasi({
|
||||
iller,
|
||||
secili,
|
||||
@@ -22,9 +31,20 @@ export function IlSecimHaritasi({
|
||||
secili: string[];
|
||||
onToggle: (il: string) => void;
|
||||
}) {
|
||||
const adetler = new Map(iller.map((i) => [i.il, i.adet]));
|
||||
const maxAdet = Math.max(1, ...iller.map((i) => i.adet));
|
||||
const seciliSet = new Set(secili);
|
||||
const { adetler, maxAdet } = useMemo(() => {
|
||||
const adetler = new Map(iller.map((i) => [i.il, i.adet]));
|
||||
let maxAdet = 1;
|
||||
for (const i of iller) if (i.adet > maxAdet) maxAdet = i.adet;
|
||||
return { adetler, maxAdet };
|
||||
}, [iller]);
|
||||
const seciliSet = useMemo(() => new Set(secili), [secili]);
|
||||
const siraliSehirler = useMemo(
|
||||
() =>
|
||||
[...NORMAL_SEHIRLER].sort(
|
||||
(a, b) => Number(seciliSet.has(a.key)) - Number(seciliSet.has(b.key)),
|
||||
),
|
||||
[seciliSet],
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -35,14 +55,7 @@ export function IlSecimHaritasi({
|
||||
aria-label="Okumak istediğin illeri haritadan seç"
|
||||
>
|
||||
{/* Seçili iller en son çizilir ki turuncu kontur komşularca örtülmesin */}
|
||||
{[...cities]
|
||||
.sort(
|
||||
(a, b) =>
|
||||
Number(seciliSet.has(normalizeIlAdi(a.name))) -
|
||||
Number(seciliSet.has(normalizeIlAdi(b.name))),
|
||||
)
|
||||
.map((city) => {
|
||||
const key = normalizeIlAdi(city.name);
|
||||
{siraliSehirler.map(({ city, key }) => {
|
||||
const adet = adetler.get(key);
|
||||
const seciliMi = seciliSet.has(key);
|
||||
const yogunluk = adet ? adet / maxAdet : 0;
|
||||
|
||||
Reference in New Issue
Block a user