
本文详解如何在 Next.js 中结合 useRouter 与 useSWR,根据 URL 查询参数(如 ?filter=completed)动态请求外部 API 并实时渲染数据,实现无刷新筛选体验。
本文详解如何在 next.js 中结合 `userouter` 与 `useswr`,根据 url 查询参数(如 `?filter=completed`)动态请求外部 api 并实时渲染数据,实现无刷新筛选体验。
在 Next.js 应用中,实现基于查询参数(query params)的动态数据筛选是常见需求——例如按状态过滤职位列表:/jobs?filter=completed、/jobs?filter=upcoming。关键在于让页面响应 URL 变化,并自动触发对应 API 请求。以下是一个生产就绪的实现方案。
✅ 核心思路
- 利用 useRouter 获取当前 query 参数(如 filter);
- 将 query 构建为动态 SWR key(如 /jobs?filter=completed),确保不同筛选条件拥有独立缓存;
- 通过 router.push() 更新 URL,触发路由跳转与 SWR 自动 revalidation;
- 封装 fetcher 函数,统一处理 axios 响应结构,提升可维护性。
✅ 完整代码示例
import axios from '@/lib/axios';
import useSWR from 'swr';
import { useRouter } from 'next/router';
const Jobs = () => {
const router = useRouter();
const { filter } = router.query;
// ✅ 定义 fetcher:支持任意带参 URL,自动解析 data.data
const fetcher = (url: string) =>
axios.get(url).then((res) => res.data.data);
// ✅ 动态 SWR key:有 filter 时带参,否则请求默认端点
const { data: jobsData, error, isLoading } = useSWR(
filter ? `/jobs?filter=${filter}` : '/jobs',
fetcher,
{
// 可选:启用错误重试、设置超时等
revalidateOnFocus: false, // 避免切页后重复请求
shouldRetryOnError: false,
}
);
// ✅ 点击按钮更新 URL(不刷新页面)
const handleFilterClick = (newFilter: string) => {
router.push({
pathname: '/jobs',
query: { filter: newFilter },
});
};
// ✅ 渲染状态与数据
if (isLoading) return <p>Loading jobs...</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2750" title="抖音下载器(Node.js)"><img
src="https://img.php.cn/upload/skill/000/000/081/178935487523053.jpg" alt="抖音下载器(Node.js)" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill2750" title="抖音下载器(Node.js)" class="overflowclass">抖音下载器(Node.js)</a>
<p class="overflowclass">抖音无水印视频下载和文案提取工具</p>
</div>
<a rel="nofollow" href="/xiazai/skill2750" title="抖音下载器(Node.js)" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>;
if (error) return <p classname="text-red-500">Failed to load jobs.</p>;
return (
<div classname="space-y-4">
{/* 筛选按钮组 */}
<div classname="flex gap-2">
<button onclick="{()"> handleFilterClick('completed')}
className={`px-4 py-2 rounded ${filter === 'completed' ? 'bg-blue-600 text-white' : 'bg-gray-200'}`}
>
Completed
</button>
<button onclick="{()"> handleFilterClick('upcoming')}
className={`px-4 py-2 rounded ${filter === 'upcoming' ? 'bg-blue-600 text-white' : 'bg-gray-200'}`}
>
Upcoming
</button>
<button onclick="{()"> handleFilterClick('cancelled')}
className={`px-4 py-2 rounded ${filter === 'cancelled' ? 'bg-blue-600 text-white' : 'bg-gray-200'}`}
>
Cancelled
</button>
</div>
{/* 职位列表 */}
{jobsData && jobsData.length > 0 ? (
<ul classname="space-y-3">
{jobsData.map((job: any) => (
<li key="{job.id}" classname="border p-4 rounded bg-white shadow-sm">
<h3 classname="font-medium">{job.title}</h3>
<p classname="text-sm text-gray-600">Status: {job.status}</p>
</li>
))}
</ul>
) : (
<p classname="text-gray-500 italic">No jobs found for this filter.</p>
)}
</div>
);
};
export default Jobs;
⚠️ 注意事项与最佳实践
- URL 编码安全:若 filter 值含特殊字符(如空格、&),请使用 encodeURIComponent(filter) 包裹,避免路由解析失败;
- 服务端渲染兼容性:router.query 在 SSR 阶段可能为空,SWR 会自动在客户端 hydration 后补全,无需额外判断;
- 缓存策略优化:可通过 dedupingInterval 或 revalidateIfStale 控制重复请求频率;
- SEO 友好性:每个 ?filter=xxx 是独立 URL,搜索引擎可分别索引,利于内容发现;
- 清除筛选:添加“全部”按钮时,传入空字符串或 undefined 并在 useSWR key 中处理为 /jobs 即可。
通过以上方式,你不仅实现了响应式筛选,还兼顾了性能(SWR 缓存)、用户体验(无刷新导航)与工程健壮性(错误处理、类型安全预留)。这是 Next.js 数据获取模式的最佳实践之一。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










