useSearchParams — query parametrlar bilan ishlash
Muammodan boshlaylik
Siz mahsulotlar sahifasini yozyapsiz. Foydalanuvchi:
- Narx bo'yicha saraladi
- "Elektronika" kategoriyasini tanladi
- Qidiruvga "iPhone" deb yozdi
- 3-sahifaga o'tdi
Hammasi ajoyib ishlayapti. Lekin foydalanuvchi sahifani yangiladi — hamma filtr va qidiruv yo'qoldi. Boshidan boshlashiga to'g'ri keldi.
Yoki do'stiga havolani yubormoqchi — lekin havola faqat
/mahsulotlar ko'rsatadi, filtrlar saqlanmagan.
Muammo: filtr holati useState da — u faqat xotirada, URL da emas.
Yechim: filtrlarni URL ga saqlash. ?kategoriya=elektronika&tartib=narx&sahifa=3
ko'rinishida. Sahifa yangilansin, havola ulashilsin — hamma narsa saqlanadi.
Bu — query parametrlar (search params). useSearchParams shu bilan ishlaydi.
Query parametr nima?
URL ning ? dan keyingi qismi — query string:
/mahsulotlar?kategoriya=elektronika&tartib=narx&sahifa=3
↑
query string boshlanadi
kategoriya, tartib, sahifa — kalitlar.
elektronika, narx, 3 — qiymatlar.
useParams :id kabi dinamik segmentlarni oladi.
useSearchParams esa ?kalit=qiymat query parametrlarini oladi.
Hayotiy o'xshatma: kutubxona katalogi. Kitob ID si —
/kitob/42 (useParams). Qidiruv filtrlari esa —
/kitoblar?janr=fantastika&yil=2023&sahifa=2 (useSearchParams).
Ikkinchisi sharoitga qarab o'zgaradi, URL da ko'rinadi,
ulashish va orqaga qaytish ishlaydi.
Asosiy ishlatilish
useSearchParams — useState ga o'xshash: [qiymat, setter] qaytaradi.
import { useSearchParams } from 'react-router-dom';
function Mahsulotlar() {
const [searchParams, setSearchParams] = useSearchParams();
// Qiymat olish
const kategoriya = searchParams.get('kategoriya'); // "elektronika" yoki null
const sahifa = searchParams.get('sahifa'); // "3" yoki null
return <div>Kategoriya: {kategoriya}</div>;
}
searchParams.get('kalit') — qiymat qaytaradi yoki null.
Query parametrlarni o'zgartirish
Yozish — setSearchParams
// Bitta parametr o'rnatish
setSearchParams({ kategoriya: 'elektronika' });
// URL: /mahsulotlar?kategoriya=elektronika
// Bir nechta parametr
setSearchParams({ kategoriya: 'elektronika', tartib: 'narx', sahifa: '1' });
// URL: /mahsulotlar?kategoriya=elektronika&tartib=narx&sahifa=1
Mavjud parametrni saqlab yangilanish
// ❌ Muammo — boshqa parametrlar o'chib ketadi
setSearchParams({ sahifa: '2' });
// Agar oldin kategoriya=elektronika bo'lsa — yo'qoladi!
// ✅ To'g'ri — mavjud parametrlarni saqlab, faqat kerakligini o'zgartirish
setSearchParams((oldingi) => {
const yangi = new URLSearchParams(oldingi);
yangi.set('sahifa', '2');
return yangi;
});
Funksiya shakli useState setter ga o'xshaydi — oldingi holatni
olib, yangi holatni qaytaradi.
URLSearchParams — yordamchi metodlar
searchParams — URLSearchParams ob'ekti. Bir nechta foydali metodi bor:
const [searchParams] = useSearchParams();
searchParams.get('kategoriya'); // bitta qiymat olish
searchParams.getAll('tag'); // bir xil kalitdagi barcha qiymatlar
searchParams.has('qidiruv'); // parametr bormi — boolean
searchParams.toString(); // "kategoriya=elektronika&sahifa=1"
getAll — bir kalit bir nechta marta kelganda:
/mahsulotlar?tag=yangi&tag=ommabop&tag=chegirma
searchParams.getAll('tag'); // ["yangi", "ommabop", "chegirma"]
To'liq misol — filtrli mahsulotlar sahifasi
// pages/Mahsulotlar.jsx
import { useSearchParams } from 'react-router-dom';
const barcha = [
{ id: 1, nomi: 'iPhone 15', kategoriya: 'telefon', narxi: 12000000 },
{ id: 2, nomi: 'MacBook Pro', kategoriya: 'noutbuk', narxi: 35000000 },
{ id: 3, nomi: 'Samsung S24', kategoriya: 'telefon', narxi: 10000000 },
{ id: 4, nomi: 'Dell XPS', kategoriya: 'noutbuk', narxi: 28000000 },
{ id: 5, nomi: 'iPad Air', kategoriya: 'planshet', narxi: 15000000 },
];
function Mahsulotlar() {
const [searchParams, setSearchParams] = useSearchParams();
const kategoriya = searchParams.get('kategoriya') || 'hammasi';
const tartib = searchParams.get('tartib') || 'ism';
// Filtrlash
const filtrlangan = barcha
.filter((m) =>
kategoriya === 'hammasi' ? true : m.kategoriya === kategoriya
)
.sort((a, b) =>
tartib === 'narx' ? a.narxi - b.narxi : a.nomi.localeCompare(b.nomi)
);
function kategoriyaOzgartir(yangiKategoriya) {
setSearchParams((oldingi) => {
const yangi = new URLSearchParams(oldingi);
yangi.set('kategoriya', yangiKategoriya);
yangi.set('sahifa', '1'); // ← kategoriya o'zgarganda 1-sahifaga qayt
return yangi;
});
}
function tartibOzgartir(yangiTartib) {
setSearchParams((oldingi) => {
const yangi = new URLSearchParams(oldingi);
yangi.set('tartib', yangiTartib);
return yangi;
});
}
return (
<div>
<h1>Mahsulotlar</h1>
{/* Kategoriya filtri */}
<div>
{['hammasi', 'telefon', 'noutbuk', 'planshet'].map((k) => (
<button
key={k}
onClick={() => kategoriyaOzgartir(k)}
style={{ fontWeight: kategoriya === k ? 'bold' : 'normal' }}
>
{k}
</button>
))}
</div>
{/* Tartib filtri */}
<select
value={tartib}
onChange={(e) => tartibOzgartir(e.target.value)}
>
<option value="ism">Ism bo'yicha</option>
<option value="narx">Narx bo'yicha</option>
</select>
{/* Natijalar */}
<ul>
{filtrlangan.map((m) => (
<li key={m.id}>
{m.nomi} — {m.narxi.toLocaleString()} so'm
</li>
))}
</ul>
</div>
);
}
export default Mahsulotlar;
Endi foydalanuvchi ?kategoriya=telefon&tartib=narx havolasini
ulashsa — boshqa odam ham aynan shu filtrlangan ko'rinishni ko'radi.
Qidiruv satri — debounce bilan
Har harf bosishda URL o'zgarsa — brauzer tarixi to'lib ketadi.
replace: true bilan bu muammo hal bo'ladi:
import { useSearchParams } from 'react-router-dom';
import { useState, useEffect } from 'react';
function QidiruvSatri() {
const [searchParams, setSearchParams] = useSearchParams();
const [matn, setMatn] = useState(searchParams.get('q') || '');
useEffect(() => {
const taymer = setTimeout(() => {
setSearchParams(
(oldingi) => {
const yangi = new URLSearchParams(oldingi);
if (matn) {
yangi.set('q', matn);
} else {
yangi.delete('q'); // ← bo'sh bo'lsa parametrni o'chir
}
return yangi;
},
{ replace: true } // ← har harf alohida tarix yozuvi bo'lmasin
);
}, 400); // ← 400ms kutib, keyin URL ni yangilaydi
return () => clearTimeout(taymer);
}, [matn, setSearchParams]);
return (
<input
value={matn}
onChange={(e) => setMatn(e.target.value)}
placeholder="Qidirish..."
/>
);
}
Sahifalash (pagination) bilan
function Mahsulotlar() {
const [searchParams, setSearchParams] = useSearchParams();
const sahifa = Number(searchParams.get('sahifa')) || 1;
const hajm = 10; // har sahifada nechta
function sahifaOzgartir(yangiSahifa) {
setSearchParams((oldingi) => {
const yangi = new URLSearchParams(oldingi);
yangi.set('sahifa', String(yangiSahifa));
return yangi;
});
}
return (
<div>
{/* mahsulotlar ro'yxati */}
<div>
<button
disabled={sahifa === 1}
onClick={() => sahifaOzgartir(sahifa - 1)}
>
← Oldingi
</button>
<span>Sahifa: {sahifa}</span>
<button onClick={() => sahifaOzgartir(sahifa + 1)}>
Keyingi →
</button>
</div>
</div>
);
}
Link bilan query parametr
<Link> ga ham query parametrlar uzatish mumkin:
import { Link } from 'react-router-dom';
// Matn ko'rinishida
<Link to="/mahsulotlar?kategoriya=telefon&tartib=narx">
Telefonlar
</Link>
// Ob'ekt ko'rinishida
<Link to={{ pathname: '/mahsulotlar', search: '?kategoriya=telefon' }}>
Telefonlar
</Link>
Tez-tez uchraydigan xatolar
1. Mavjud parametrlarni o'chirmay yangilash
// ❌ Xato — boshqa parametrlar yo'qoladi
setSearchParams({ sahifa: '2' });
// Oldin: ?kategoriya=telefon&sahifa=1
// Keyin: ?sahifa=2 ← kategoriya yo'qoldi!
// ✅ To'g'ri — funksiya shakli bilan
setSearchParams((oldingi) => {
const yangi = new URLSearchParams(oldingi);
yangi.set('sahifa', '2');
return yangi;
// Keyin: ?kategoriya=telefon&sahifa=2
});
Sababi: setSearchParams({...}) to'liq almashtiradi —
ko'rsatilmagan parametrlar o'chib ketadi. Funksiya shakli esa
oldingi holatni saqlab, faqat kerakligini o'zgartiradi.
2. Qiymatni raqamga o'girmaslik
// ❌ Xato — string bilan hisoblash
const sahifa = searchParams.get('sahifa'); // "3"
const keyingi = sahifa + 1; // "31" — string concatenation!
// ✅ To'g'ri — Number() bilan o'girish
const sahifa = Number(searchParams.get('sahifa')) || 1;
const keyingi = sahifa + 1; // 4
Sababi: searchParams.get() har doim string qaytaradi.
Matematik amallar uchun raqamga o'girish shart.
3. Yo'q parametrni ishlatganda null ni hisobga olmaslik
// ❌ Xato — null bo'lishi mumkin
const kategoriya = searchParams.get('kategoriya');
// URL da ?kategoriya yo'q bo'lsa — null
kategoriya.toUpperCase(); // TypeError: Cannot read properties of null
// ✅ To'g'ri — default qiymat bilan
const kategoriya = searchParams.get('kategoriya') || 'hammasi';
Sababi: Parametr URL da bo'lmasa get() null qaytaradi.
Har doim default qiymat yoki ?. optional chaining ishlatish kerak.
4. Qidiruv satriga debounce qo'ymaslik
// ❌ Xato — har harf bosishda URL o'zgaradi
function QidiruvSatri() {
const [searchParams, setSearchParams] = useSearchParams();
return (
<input
onChange={(e) => setSearchParams({ q: e.target.value })}
/>
);
// Foydalanuvchi "iPhone" yozsa: brauzer tarixida
// i → iP → iPh → iPho → iPhon → iPhone — 6 ta yozuv!
}
Sababi: Har harf bosishda setSearchParams chaqirilsa —
brauzer tarixiga alohida yozuv qo'shiladi. "Orqaga" tugmasi
harfma-harf qaytadi. Yechim: debounce va replace: true.
Xulosa
useSearchParams— URL dagi?kalit=qiymatbilan ishlashsearchParams.get('kalit')— qiymat olish (string yoki null)setSearchParams({ ... })— to'liq almashtiradisetSearchParams(oldingi => ...)— mavjud parametrlarni saqlab yangilaydireplace: true— qidiruv satri uchun, tarixga ortiqcha yozmaslik- Qiymatlar har doim string — raqam kerak bo'lsa
Number()ishlatish nullbo'lishi mumkin — default qiymat bilan himoya qilish
Keyingi dars: 45-dars: Nested Routes — ichma-ich route lar, Outlet