过滤, 并置入下一张. js 15 实际使用的图案

2026年8月7日1 次浏览来源:Dev.to阅读原文

正文保留英文原文(机翻易破坏代码与排版),标题/摘要已提供中文

Every dashboard eventually needs the same three things.

A search box, a few filters, and pagination once the list gets long.

The version I used to build kept all of that in , which meant losing your filters the moment you refreshed the page or shared a link with someone else.

Keeping this state in the URL instead fixed both problems at once.

Here is the setup.

1.

Why URL Search Params, Not State in disappears on refresh and cannot be shared or bookmarked.

The same filtered, paginated view living in the URL means a refresh keeps your place, a shared link shows the same filtered results to whoever opens it, and the browser's back button actually works the way people expect.

This URL alone fully describes the current view.

No client state needs to reconstruct it.

2.

Reading Search Params in a Server Component The page itself stays a Server Component, fetching exactly the data described by the current URL.

No loading state needed here either, Next.js handles the transition with if the query is slow.

3.

The Query Function Running and in parallel with matters here, they are independent queries and there is no reason to wait for one before starting the other.

4.

Updating the URL from Filter Inputs The filter component itself is a Client Component, since it responds to user interaction, but it never holds the actual filtered data.

It only ever updates the URL, and the Server Component above reacts to that.

Two things matter here.

The 400ms debounce on the search input stops a fetch from firing on every keystroke, only after the user pauses typing.

And resetting to on any filter change avoids landing on an empty page 4 after a new filter reduces the total result count below that.

5.

Pagination Controls Reusing the existing search params and only changing keeps the current search and filters intact when navigating between pages, instead of accidentally clearing them.

6.

Combining Search with a Real Text Index A search works fine for small collections, but scans the full collection on every query as it grows.

For anything beyond a few thousand documents, a real text index performs much better.

MongoDB's text index handles this far more efficiently than a regex scan once the collection grows, at the cost of slightly less flexible partial matching than regex offers.

Summary Pattern Handles URL search params instead of Shareable, bookmarkable, refresh-safe filtered views Server Component reading Data fetching that reacts directly to the URL Debounced input before updating the URL Avoiding a fetch on every keystroke Reset to 1 on filter change Avoiding landing on an empty page after filtering for count and results Running independent queries in parallel Text index over regex at scale Performance once the collection grows beyond a few thousand records The shift that matters most here: the URL is the state.

The Server Component just reads it and fetches accordingly, and the filter UI's only job is updating that URL, never holding the actual result data itself.

I use this exact URL-driven pattern, debounced search, filters, pagination, across every dashboard and admin panel I build.

See it in a real codebase: https://neurodash-dashbord.vercel.app/ Get the templates: https://pixelanas.gumroad.com Do you keep filter state in the URL, or in a client store?

Drop it below 👇 Anas, full-stack Next.js developer building SaaS products and premium templates.

X: @ASheikh69751

分享