停止在 Next.js 中手动管理 URLSearchParams — 改用 nuqs
Source: Dev.to
现代 Web 应用经常在 URL 中表示 UI 状态,例如:
- 搜索过滤器
- 分页
- 排序
- 标签选择
- 仪表盘参数
一个典型的 URL 可能是这样的:
/products?category=books&sort=price&page=2将 UI 状态与 URL 同步可以提升多方面的体验:
- 可分享性 – 用户可以分享已过滤的视图
- 书签
- 浏览器导航(前进/后退)
- 可预测的应用状态
然而,在 Next.js App Router 中实现这一点往往会产生重复且脆弱的代码。
最近我开始使用一个名为 nuqs 的库,它显著提升了管理 URL 状态时的开发者体验。
本文将涵盖:
- 手动管理查询参数为何痛苦
- 我为何选择 nuqs
- 如何在实际项目中使用它
- 我的开发工作流有哪些改进
问题:手动管理 URL 状态
如果没有辅助库,管理 URL 状态通常需要组合以下内容:
useSearchParamsuseRouterURLSearchParamsuseStateuseEffect
示例
'use client'
import { useRouter, useSearchParams } from 'next/navigation'
import { useState, useEffect } from 'react'
export default function ProductFilter() {
const router = useRouter()
const searchParams = useSearchParams()
const [category, setCategory] = useState(
searchParams.get('category') ?? ''
)
useEffect(() => {
const params = new URLSearchParams(searchParams)
params.set('category', category)
router.push(`?${params.toString()}`)
}, [category, router, searchParams])
return (
setCategory(e.target.value)}
>
All
Books
Games
)
}问题 ⚡️
- 到处都是样板代码
- 手动解析
URLSearchParams - 难以在多个过滤器之间扩展
- 容易引入 bug
- 没有内置的类型安全
随着应用规模的增长(例如搜索页面或仪表盘),这些逻辑很快就变得难以维护。
什么是 nuqs?
nuqs 是一个轻量级库,它将 URL 查询参数视为 React 状态。
无需手动同步状态和 URL,只需使用一个 hook。
URL Query React State这大大简化了查询参数的管理。
安装 nuqs
npm install nuqs
# or
yarn add nuqs
# or
pnpm add nuqs就这样。
使用 nuqs 的相同示例
'use client'
import { useQueryState } from 'nuqs'
export default function ProductFilter() {
const [category, setCategory] = useQueryState('category')
return (
setCategory(e.target.value)}
>
All
Books
Games
)
}当状态变化时,URL 会自动更新。
生成的 URL
/products?category=books与手动实现相比:
- 没有路由逻辑
- 没有
useEffect - 没有手动查询解析
类型安全的查询参数
nuqs 最强大的功能之一是它的解析器系统。
示例:分页
import { useQueryState, parseAsInteger } from 'nuqs'
const [page, setPage] = useQueryState(
'page',
parseAsInteger.withDefault(1)
)优势
page始终是数字- 默认值为
1 - 无效的查询值会被安全处理
这可以防止许多运行时错误。
管理多个查询参数
复杂的 UI 通常有多个过滤器。nuqs 使用 useQueryStates 干净地处理这些。
import { useQueryStates, parseAsString } from 'nuqs'
const [filters, setFilters] = useQueryStates({
category: parseAsString,
sort: parseAsString,
})更新过滤器
setFilters({
category: 'books',
sort: 'price',
})生成的 URL
?category=books&sort=price这使得过滤逻辑可预测且易于维护。
为什么我选择 nuqs
在为 URL 状态管理选择库时,我考虑了多个因素。
1. 开发者体验
nuqs 消除了手动同步状态和 URL 的需求。
不再需要在 useEffect、URLSearchParams 和路由更新之间来回切换,查询参数的使用就像普通的 React 状态一样。这大幅减少了样板代码并提升了可读性。
2. 类型安全
解析器系统允许对查询参数进行类型定义,确保值的可预测性,并在 TypeScript 项目中降低运行时错误的可能性。
3. 零依赖 & 轻量
nuqs 没有运行时依赖,这带来了多项优势:
- 更小的 bundle 大小
- 更少的潜在安全漏洞
- 降低依赖冲突风险
- 更易于长期维护
在现代前端项目中,依赖树往往会迅速膨胀。使用依赖最小化的专注库有助于保持应用的精简,而 nuqs 正是遵循了这一理念。
4. 为现代 Next.js 设计
nuqs 能自然地与 Next.js App Router 和 React Hook 集成。它无缝契合现代 React 架构,而不会引入额外的复杂性。
我的项目中的真实影响
在采用 nuqs 之后,我观察到:
- 约 30% 的减少 在与 URL 处理相关的组件样板代码上
- 更少的错误 由格式错误的查询字符串引起(得益于类型安全的解析器)
- 新成员的上手速度更快,因为 API 直观且自带文档
- 更清晰的关注点分离:UI 组件不再需要了解路由细节
总体而言,nuqs 将我代码库中一个痛苦且易出错的部分转变为声明式、类型安全的体验。
TL;DR
如果你正在构建一个依赖查询参数来管理 UI 状态的 Next.js 应用,试试 nuqs 吧。它将 URL 管理转变为简单的基于 hook 的工作流,提供类型安全,并保持你的 bundle 轻量。祝编码愉快!
引入 nuqs 时,几个改进变得显而易见
更少的模板代码
查询状态逻辑显著变得更小、更易于理解。
更好的可维护性
添加新过滤器现在只需几行代码。
更少的错误
类型安全的解析可防止无效的查询状态。
更佳的用户体验
由于 UI 状态保存在 URL 中:
- 过滤器可以共享
- 页面可以收藏
- 浏览器导航自然工作
当 nuqs 特别有用时
根据我的经验,nuqs 在以下场景表现尤为出色:
- 搜索 / 过滤页面
- 电子商务列表
- 仪表盘
- 分析工具
- 分页系统
- 排序 UI
换句话说:
✨ 任何需要将 UI 状态反映在 URL 中的界面。
最后思考
在 Next.js 中手动管理 URL 状态往往会导致代码重复且脆弱。
nuqs 提供了一个简洁的抽象,将查询参数视为 React 状态,同时保持类型安全且轻量。
对于现代的 React 和 Next.js 应用,它可以显著提升:
- 开发者体验
- 代码可维护性
如果你正在构建大量过滤器的界面或仪表盘,我强烈推荐尝试 nuqs!