Lưu trên URL query param, không phải useState hay store global. State đó thuộc về URL 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.