Use as Filter

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.


Try it out

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: number
name: string
status: string
image: 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>
)
}