停止在 Next.js 中手动管理 URLSearchParams — 改用 nuqs

发布: (2026年3月13日 GMT+8 22:03)
8 分钟阅读
原文: Dev.to

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 状态通常需要组合以下内容:

  • useSearchParams
  • useRouter
  • URLSearchParams
  • useState
  • useEffect

示例

'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 的需求。
不再需要在 useEffectURLSearchParams 和路由更新之间来回切换,查询参数的使用就像普通的 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!

0 浏览
Back to Blog

相关文章

阅读更多 »