A directory that full-reloads on every filter click feels broken on any connection slower than corporate fiber. Each reload throws away scroll position, re-runs layout shift, refetches unchanged header and footer chunks, and adds 200-800ms of perceived latency per filter adjustment. Users who would have iterated through three or four filter combinations abandon after one. Modern directories live or die on the speed at which users can refine results — a full-page refresh loop is the single largest UX regression in this category.
Critical because filter interactions are the core refinement loop and page reloads collapse iteration speed below the threshold where users keep exploring.
Fetch filtered results from a JSON API endpoint and update component state in place. Keep the URL in sync for sharability and back/forward navigation, but use router.push with client routing, not a hard navigation. Edit components/FilteredListings.tsx:
const handleFilterChange = async (next) => {
setLoading(true)
const res = await fetch(`/api/listings?${new URLSearchParams(next)}`)
setResults((await res.json()).listings)
setLoading(false)
}
ID: directory-search-discovery.facets-filters.filter-no-reload
Severity: critical
What to look for: Enumerate all relevant files and In the browser dev tools, open the Network tab or disable JavaScript animations. Apply a filter (e.g., select a category, price range, or rating). Observe whether the page reloads (full page refresh, spinner that covers the entire page) or whether the results update in place (AJAX/fetch request, local state update with a loading spinner on the results area only).
Pass criteria: Applying any filter updates the results without a full page reload. Results may show a loading spinner or skeleton state, but the page itself does not refresh. The URL updates to reflect the filter (expected), but this is a browser history update, not a page reload.
Fail criteria: Applying a filter causes a full page reload (browser reload/refresh), or results do not update at all, or a filter is applied but the results remain unchanged.
Skip (N/A) when: Directory has fewer than 3 filterable attributes (see Global N/A Rule).
Detail on fail: "Applying the category filter causes a full page reload (network tab shows document request). Should update results via AJAX." or "Filter selections do not update the results — results remain the same after clicking a filter." or "Filter applied but results disappear, showing error or blank state."
Remediation: Implement filter updates via client-side state and API calls, not full-page navigation:
// components/FilteredListings.tsx
import { useState } from 'react'
export function FilteredListings() {
const [filters, setFilters] = useState({ category: null, price: null })
const [results, setResults] = useState([])
const [loading, setLoading] = useState(false)
const handleFilterChange = async (newFilters) => {
setFilters(newFilters)
setLoading(true)
const params = new URLSearchParams(newFilters)
const res = await fetch(`/api/listings?${params}`)
const data = await res.json()
setResults(data.listings)
setLoading(false)
}
return (
<div>
<FilterPanel onChange={handleFilterChange} />
{loading && <div>Loading...</div>}
<ListingGrid listings={results} />
</div>
)
}
Fetch filtered results via an API endpoint (e.g., /api/listings?category=restaurants&price=0-50) and update the results in state. Also update the URL to preserve the filter state for sharing and back/forward navigation.