Lưu trên URL query param, không phải useState hay store global. URL là nơi state đó thuộc về vì nó mô tả "user đang xem cái gì".
Lợi ích cụ thể:
- Chia sẻ được: copy link gửi đồng nghiệp ra đúng kết quả đã lọc.
- F5 không mất, nút back/forward hoạt động đúng như kỳ vọng.
- Trở thành một phần queryKey của React Query nên cache tự tách theo bộ lọc.
tsx
const params = useSearchParams()
const page = Number(params.get('page') ?? 1)
const q = params.get('q') ?? ''
const { data } = useQuery({
queryKey: ['products', { q, page }],
queryFn: () => fetchProducts({ q, page }),
})Hai lưu ý khi triển khai: ô search nên debounce rồi mới ghi URL để không tạo hàng chục entry history (dùng router.replace thay vì push cho thao tác gõ phím); và trong Next.js App Router, component gọi useSearchParams cần nằm trong <Suspense> để phần còn lại của trang vẫn prerender được.