This guide demonstrates how to implement filtering with dynamic data fetching, search parameters, and pagination. This example uses the Rick and Morty API to show characters with filtering capabilities.
Start searching for characters
'use client'import { useState, useEffect } from 'react'import { useForm } from 'react-hook-form'import { usePathname, useSearchParams } from 'next/navigation'import { Button } from '@/components/ui/button'import { Input } from '@/components/ui/input'import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'import { Pagination, PaginationContent, PaginationItem, PaginationLink } from '@/components/ui/pagination'import { useSearchQuery } from 'use-search-query'interface Character {id: numbername: stringstatus: stringimage: string}export default function CharacterFilter() {const { routeToSearchParams } = useSearchQuery()const pathname = usePathname()const searchParams = useSearchParams()const { register, handleSubmit } = useForm({defaultValues: {name: searchParams.get('name') || '',status: searchParams.get('status') || ''}})const [characters, setCharacters] = useState<Character[]>([])const [loading, setLoading] = useState(false)const currentPage = parseInt(searchParams.get('page') || '1')useEffect(() => {const fetchCharacters = async () => {setLoading(true)const params = new URLSearchParams()if (searchParams.get('name')) params.append('name', searchParams.get('name')!)if (searchParams.get('status')) params.append('status', searchParams.get('status')!)params.append('page', currentPage.toString())const response = await fetch(`https://rickandmortyapi.com/api/character?${params}`)const data = await response.json()setCharacters(data.results || [])setLoading(false)}fetchCharacters()}, [searchParams, currentPage])function onSubmit(data: { name: string; status: string }) {routeToSearchParams(pathname, {name: data.name || undefined,status: data.status || undefined,page: undefined})}return (<div className="space-y-6"><form onSubmit={handleSubmit(onSubmit)} className="space-y-4"><Input {...register('name')} placeholder="Search by name..." /><select {...register('status')}><option value="">All Status</option><option value="alive">Alive</option><option value="dead">Dead</option></select><Button type="submit">Search</Button></form>{loading && <p>Loading...</p>}<div className="grid grid-cols-3 gap-4">{characters.map(char => (<div key={char.id} className="border rounded p-4"><img src={char.image} alt={char.name} /><h3>{char.name}</h3><p>{char.status}</p></div>))}</div><Pagination><PaginationContent>{/* Pagination items */}</PaginationContent></Pagination></div>)}