使用 nuqs 在 Next.js 中管理 URL 查询字符串状态

1,040 阅读3分钟

在开发现代 web 应用时,状态管理是一个非常重要的部分。通常,我们会使用 React.useState 来管理组件的状态。然而,有时候我们希望状态能够与 URL 的查询字符串同步,这样用户可以通过直接修改 URL 来改变页面状态。为此,nuqs 提供了一个非常便捷的解决方案,让你可以轻松地将状态存储在 URL 查询字符串中。

什么是 nuqs

nuqs 是一个为 Next.js 设计的自定义 Hook,功能类似于 React.useState,但它的状态是存储在 URL 的查询字符串中。这意味着状态的变化会直接反映在 URL 上,并且可以通过直接编辑 URL 来影响页面状态。

核心功能

  • 支持 Next.js 的 app 和 pages 两种路由方式
  • URL 是唯一的状态来源:简单明了,状态通过 URL 传递和保存。
  • 历史记录管理:支持使用浏览器的后退按钮来导航状态变化。
  • 内置解析器:支持常见的数据类型(整数、浮点数、布尔值、日期等)的解析。
  • 批量处理查询字符串:通过 useQueryStates 可以处理多个相关的查询字符串。
  • 默认使用浅模式:URL 更新时默认不会触发服务端的重新渲染,但可以选择通知服务端更新。

安装

你可以通过以下任意一个命令安装 nuqs

pnpm add nuqs
yarn add nuqs
npm install nuqs

注意:nuqs 之前的名字是 next-usequerystate,从 2.x 版本开始,包名改为 nuqs。如果你使用的是较旧的 Next.js 版本(< 13.1),请继续使用 next-usequerystate

基本使用方法

假设我们有一个简单的页面,可以通过 URL 查询字符串来设置用户的名称:

useQueryState.gif

'use client'

import { useQueryState } from 'nuqs'

export default function HelloPage() {
  const [name, setName] = useQueryState('name')

  return (
    <div>
      <h1>Hello, {name || 'anonymous visitor'}!</h1>
      <input value={name || ''} onChange={e => setName(e.target.value)} />
      <button onClick={() => setName(null)}>Clear</button>
    </div>
  )
}

在这个例子中,useQueryState 会从 URL 中提取 name 参数,并将其作为组件状态。如果 URL 中没有 name 参数,则状态为 null。我们还可以通过输入框来更改 name,更改后 URL 会自动更新。

状态解析

默认情况下,useQueryState 返回的是字符串类型的状态值。如果需要处理其他类型的数据(如整数、浮点数等),可以使用内置的解析器。例如:

import { useQueryState, parseAsInteger } from 'nuqs'

export default function CounterPage() {
  const [count, setCount] = useQueryState('count', parseAsInteger.withDefault(0))

  return (
    <div>
      <pre>count: {count}</pre>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
      <button onClick={() => setCount(null)}>Clear</button>
    </div>
  )
}

在这个例子中,我们通过 parseAsInteger 解析器将 count 参数解析为整数,并设置默认值为 0。

多状态管理

如果需要同时管理多个查询字符串参数,可以使用 useQueryStates

import { useQueryStates, parseAsFloat } from 'nuqs'

export default function MapPage() {
  const [coordinates, setCoordinates] = useQueryStates({
    lat: parseAsFloat.withDefault(45.18),
    lng: parseAsFloat.withDefault(5.72)
  })

  return (
    <div>
      <h1>Map Coordinates</h1>
      <p>Latitude: {coordinates.lat}</p>
      <p>Longitude: {coordinates.lng}</p>
      <button onClick={() => setCoordinates({ lat: 48.8566, lng: 2.3522 })}>Set to Paris</button>
    </div>
  )
}

useQueryStates 允许你同时管理多个查询字符串参数,并确保它们的状态保持一致。

更多高级功能

nuqs 还支持一些高级功能,如:

  • 历史记录管理:你可以选择在状态更新时是替换当前历史记录还是新增一条记录。
  • 服务器端解析:支持在服务器组件中解析查询字符串。
  • 防抖与节流:在高频率更新状态时,nuqs 会自动节流 URL 更新,以避免浏览器性能问题。

nuqs 是一个强大且灵活的工具,尤其适合在 Next.js 项目中管理 URL 查询字符串状态。通过将状态存储在 URL 中,用户可以方便地通过分享链接或直接修改 URL 来改变页面状态。同时,它也提供了丰富的解析器和配置选项,让你可以根据需求精细控制状态的行为。无论是简单的输入框还是复杂的多状态管理,nuqs 都能帮助你轻松实现。