nuqs 2

向其他 React 框架开放

François Best

@francoisbest.com

22 October 2024


nuqs@2.0.0 已可用,现在就试试吧:

npm install nuqs@latest

它带来了令人兴奋的新功能和改进,包括:


你好,React! 👋 ⚛️

nuqs 最初是一个仅限 Next.js 的钩子,而 v2 带来了与其他 React 框架的兼容性:

  • Next.js 14 & 15(app & pages 路由器)
  • React SPA
  • Remix
  • React Router

使用 nuqs 钩子的组件无需更改代码, 使它们在所有支持的框架中实现 通用性

唯一的新要求是将你的 React 树用相应框架的 适配器 包裹。

使用 Vite 的 React SPA 示例:

src/main.tsx
import { NuqsAdapter } from 'nuqs/adapters/react'

createRoot(document.getElementById('root')!).render(
  <NuqsAdapter>
    <App />
  </NuqsAdapter>
)

适配器文档 包含所有支持框架的示例。

测试

nuqs v1 的一个主要痛点是测试使用其钩子的组件。

Nuqs v2 带有内置 测试适配器,它模拟 URL 行为, 允许你在任何框架运行时之外隔离测试组件。

你可以使用任何渲染 React 组件的单元测试框架 (我推荐 Vitest & Testing Library)。

counter-button.test.tsx
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { NuqsTestingAdapter, type UrlUpdateEvent } from 'nuqs/adapters/testing'
import { describe, expect, it, vi } from 'vitest'
import { CounterButton } from './counter-button'

it('should increment the count when clicked', async () => {
  const user = userEvent.setup()
  const onUrlUpdate = vi.fn<[UrlUpdateEvent]>()
  render(<CounterButton />, {
    // 1. 通过传递初始搜索参数 / 查询字符串来设置测试:
    wrapper: ({ children }) => (
      <NuqsTestingAdapter searchParams="?count=42" onUrlUpdate={onUrlUpdate}>
        {children}
      </NuqsTestingAdapter>
    )
  })
  // 2. 执行操作
  const button = screen.getByRole('button')
  await user.click(button)
  // 3. 断言状态变化以及(模拟的)URL 变化
  expect(button).toHaveTextContent('count is 43')
  expect(onUrlUpdate).toHaveBeenCalledOnce()
  expect(onUrlUpdate.mock.calls[0][0].queryString).toBe('?count=43')
  expect(onUrlUpdate.mock.calls[0][0].searchParams.get('count')).toBe('43')
  expect(onUrlUpdate.mock.calls[0][0].options.history).toBe('push')
})

该适配器符合 setup / act / assert 测试策略,允许你:

  1. 设置初始 URL 搜索参数
  2. 让测试框架在组件上执行操作
  3. 断言 URL 作为结果而发生的变化

破坏性变更与迁移

最大的破坏性变更就是引入了 适配器。 另一个变更与已弃用的 API 相关。

开启这段旅程的 next-usequerystate 包不再更新。 所有更新现在都发布在 nuqs 包名下。

现在支持的最低 Next.js 版本是 14.2.0。它兼容 Next.js 15,包括服务器端缓存中的异步 searchParams 页面属性 (/docs/server-side)。

基于社区反馈,有一些重要的行为变更:

阅读完整的 迁移指南 来更新你的 应用程序。

捆绑大小改进

通过转向 仅 ESM,并放弃支持旧版 Next.js 所需的黑客技巧, 捆绑大小现在比 v1 小 20%。它也是 无副作用的可树摇 的。

未来计划?

社区和我对 nuqs 的未来有很多想法,包括:

  • 在所有支持的 React 框架中提供统一、可扩展、类型安全的路由体验
  • 社区贡献的解析器与适配器
  • 新选项:防抖、全局默认值覆盖
  • 用于将旧 URL 迁移到新 URL 的中间件
  • 更好的 Zod 集成,用于类型安全与运行时安全的验证

致谢

我想感谢 赞助者贡献者 以及在 GitHubX/Twitter 上提出问题和讨论的人。 你们是推动这个项目前进的不断增长的社区, 我对反馈感到非常高兴。

赞助者

感谢这些了不起的人,我能够投入更多时间到这个项目中,让它变得更好。 在 GitHub Sponsors 上加入他们!

贡献者

衷心感谢 @andreisocaciu@tordans@prasannamestha@Talent30@neefrehman@chbg@dopry@weisisheng@hugotiger@iuriizaporozhets@rikbrown@mateogianolio@timheerwagen@psdmsft@psdewar 的帮助!