DEV Community

Nana Okamoto
Nana Okamoto

Posted on

Stop Manually Managing URLSearchParams in Next.js — Use nuqs Instead

Modern web applications often represent UI state in the URL.

For example:

  • search filters
  • pagination
  • sorting
  • tab selection
  • dashboard parameters

A typical URL might look like this:

/products?category=books&sort=price&page=2
Enter fullscreen mode Exit fullscreen mode

Synchronizing UI state with the URL improves several things:

  • shareability (users can share filtered views)
  • bookmarking
  • browser navigation
  • predictable application state

However, implementing this in Next.js App Router often leads to repetitive and fragile code.

Recently I started using a library called nuqs, and it significantly improved the developer experience when managing URL state.

In this article I'll cover:

  • why managing query parameters manually is painful
  • why I chose nuqs
  • how to use it in real projects
  • what improved in my development workflow

The Problem: Manual URL State Management

Without a helper library, managing URL state usually requires combining:

  • useSearchParams
  • useRouter
  • URLSearchParams
  • useState
  • useEffect

Example:

'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])

  return (
    <select
      value={category}
      onChange={(e) => setCategory(e.target.value)}
    >
      <option value="">All</option>
      <option value="books">Books</option>
      <option value="games">Games</option>
    </select>
  )
}
Enter fullscreen mode Exit fullscreen mode

While this works, it introduces several problems.

Problems ⚡️

• Boilerplate code everywhere
• Manual parsing of URLSearchParams
• Hard to scale with multiple filters
• Easy to introduce bugs
• No built-in type safety

As applications grow (for example search pages or dashboards), this logic quickly becomes hard to maintain.

What Is nuqs?

nuqs is a lightweight library that treats URL query parameters as React state.
Instead of manually synchronizing state and the URL, you simply use a hook.
Conceptually:

URL Query <-> React State
Enter fullscreen mode Exit fullscreen mode

This drastically simplifies query parameter management.

Installing nuqs

npm install nuqs
Enter fullscreen mode Exit fullscreen mode

That's it.

The Same Example Using nuqs

Here is the same filter example rewritten with nuqs.

'use client'

import { useQueryState } from 'nuqs'

export default function ProductFilter() {
  const [category, setCategory] = useQueryState('category')

  return (
    <select
      value={category ?? ''}
      onChange={(e) => setCategory(e.target.value)}
    >
      <option value="">All</option>
      <option value="books">Books</option>
      <option value="games">Games</option>
    </select>
  )
}
Enter fullscreen mode Exit fullscreen mode

The URL automatically updates when the state changes.

Example result:

/products?category=books
Enter fullscreen mode Exit fullscreen mode

Compared to the manual implementation:

  • no router logic
  • no useEffect
  • no manual query parsing

Type-Safe Query Parameters

One of the most powerful features of nuqs is its parser system.
Example: pagination.

import { useQueryState, parseAsInteger } from 'nuqs'

const [page, setPage] = useQueryState(
  'page',
  parseAsInteger.withDefault(1)
)
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • page is always a number
  • default value is 1
  • invalid query values are handled safely

This prevents many runtime bugs.

Managing Multiple Query Parameters

Complex UIs usually have multiple filters.
nuqs handles this cleanly using useQueryStates.

import { useQueryStates, parseAsString } from 'nuqs'

const [filters, setFilters] = useQueryStates({
  category: parseAsString,
  sort: parseAsString
})
Enter fullscreen mode Exit fullscreen mode

Updating the filters:

setFilters({
  category: 'books',
  sort: 'price'
})
Enter fullscreen mode Exit fullscreen mode

Resulting URL:

?category=books&sort=price
Enter fullscreen mode Exit fullscreen mode

This keeps filter logic predictable and easy to maintain.

Why I Chose nuqs

When selecting a library for URL state management, I considered several factors.

1. Developer Experience

nuqs removes the need to manually synchronize state and the URL.

Instead of managing useEffect, URLSearchParams, and router updates, query parameters behave like React state.

This dramatically reduces boilerplate and improves readability.

2. Type Safety

The parser system allows query parameters to be typed.
This ensures predictable values and reduces runtime errors in TypeScript projects.

3. Zero Dependencies and Lightweight

Another reason I chose nuqs is that it has zero runtime dependencies.
This is important for several reasons:

  • smaller bundle size
  • fewer potential security vulnerabilities
  • lower risk of dependency conflicts
  • easier long-term maintenance

In modern frontend projects, dependency trees can grow quickly.
Using focused libraries with minimal dependencies helps keep applications lean.

nuqs follows this philosophy very well.

4. Designed for Modern Next.js

nuqs integrates naturally with Next.js App Router and React hooks.
It fits well into modern React architectures without introducing additional complexity.

Real Impact in My Project

After introducing nuqs, several improvements became clear.

Less Boilerplate
Query state logic became significantly smaller and easier to understand.

Better Maintainability
Adding new filters now requires only a few lines.

Fewer Bugs
Type-safe parsing prevents invalid query states.

Better UX
Because the UI state lives in the URL:

  • filters can be shared
  • pages can be bookmarked
  • browser navigation works naturally

When nuqs Is Especially Useful

From my experience, nuqs works especially well for:

  • search/filter pages
  • e-commerce listings
  • dashboards
  • analytics tools
  • pagination systems
  • sorting UIs

In other words:
✨ any interface where UI state should be reflected in the URL.

Final Thoughts

Managing URL state manually in Next.js often leads to repetitive and fragile code.

nuqs provides a clean abstraction that treats query parameters as React state while keeping everything type-safe and lightweight.

For modern React and Next.js applications, it can significantly improve both:

  • developer experience
  • code maintainability

If you're building filter-heavy interfaces or dashboards, I highly recommend giving nuqs a try!

Top comments (0)