Skip to main content

Command Palette

Search for a command to run...

nuqs - Type-safe search params state manager for React

Updated
5 min read
nuqs - Type-safe search params
state manager for React

Are you tired of cumbersome query parameter handling in your React applications? State management that syncs with the URL can often feel complex, but a powerful, tiny library called nuqs aims to change that, making URL management feel like an integral part of your design conversation.

nuqs is a type-safe search params state manager for React. It provides end-to-end type safety between Server and Client components, simplifying your URL logic "like magic". Best of all, it offers a familiar, simple API that makes lifting state to the URL extremely easy. At only 6 kB gzipped, nuqs is a feature-rich, customizable, and thoroughly tested library.

1.Simple State Management with useQueryState

The core strength of nuqs is its simplicity, mimicking the structure of standard React state hooks. If you currently use React.useState to manage local UI state, you can replace it with useQueryState to seamlessly sync that state with the URL.

The useQueryState hook requires one argument the key to be used in the query string. Like React.useState, it returns an array containing the value present in the query string (as a string or null if not found) and a state updater function

'use client'
import { useQueryState } from 'nuqs'

export function Demo () {
  const [name, setName] = useQueryState('name')
  // ... returns name (string or null) and setName function
}

A crucial feature is the handling of default values and types. By default, useQueryState returns a string or null. However, using built-in parsers (like parseAsInteger) allows you to define the expected type and provide a default value

import { useQueryState, parseAsInteger } from 'nuqs'

// `count` will be a number, defaulting to 0 if not in the URL
const [count, setCount] = useQueryState('count', parseAsInteger.withDefault(0))

Using .withDefault(0) ensures that count will never be null, simplifying state updates (e.g., setCount(c => c + 1)).

Note that this default value is internal to React and will not be written to the URL unless you set it explicitly. If you wish to remove a key from the query string entirely, simply set the state value to null

2.Universal Compatibility with Adapters

Since version 2, nuqs has embraced universal compatibility across a variety of React frameworks. This is achieved by wrapping your application entry point with the NuqsAdapter context provider.

Supported frameworks include

  • Next.js (App router and Pages router)

  • React SPA (e.g., with Vite)

  • Remix

  • React Router v6 and v7

  • TanStack Router (experimental support)

For instance, when using the Next.js App router, you wrap your components in the root layout file:

// src/app/layout.tsx 
import { NuqsAdapter } from 'nuqs/adapters/next/app'
// ...
< NuqsAdapter > { children } </ NuqsAdapter >

Server-Side Framework Considerations

If you are using a non-JavaScript server (like Django, Rails, or Laravel) and need the web server to be notified when the URL state changes (for server-side rendering other parts of the application), you can enable full-page navigation for updates configured with shallow: false. This option, introduced in version 2.4.0, is set on the adapter

<NuqsAdapter fullPageNavigationOnShallowFalseUpdates>

3.Advanced State Management and Server-Side Features

While useQueryState is great for single keys, nuqs offers tools for handling multiple states and integrating seamlessly with server components.

Managing Multiple Keys with useQueryStates For query keys that should always move together, the useQueryStates hook is available. You pass it an object defining all keys and their parsers:

import { useQueryStates, parseAsFloat } from 'nuqs' 

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

The setCoordinates function allows you to update all (or a subset of) the keys in a single go. All state updates are batched and applied asynchronously to the URL. Furthermore, passing null to the state updater function will clear all keys managed by that useQueryStates hook.

Shorter, Cleaner URLs To ensure that your variable names are readable within your codebase (e.g., latitude) while keeping your URLs short (e.g., lat), you can use the urlKeys option within the hook settings

const [{ latitude, longitude }, setCoordinates] = useQueryStates({ /* ...parsers */ }, {
  urlKeys: {
    latitude: 'lat',
    longitude: 'lng'
  }
})
// This results in URLs like: ?lat=45.18&lng=5.72

Type-Safe Server-Side Reading (Next.js/Remix)

nuqs provides essential tools for accessing search params type-safely on the server. Loaders Introduced in version 2.3.0, loaders allow you to parse search parameters server-side using the createLoader function.

The resulting loader function can parse search params from various sources, including Request objects, full URLs, URLSearchParams objects, or standard key-value records. For example, in a Next.js App Router component, you can consume search parameters asynchronously:

// Example Server Component usage:
const { latitude, longitude } = await loadSearchParams(searchParams)

If you need stricter parsing behavior, you can enable strict mode. By default, if an invalid value is found for a parser (e.g., ?count=banana for an integer), the default value is returned.

In strict mode, loadSearchParams will throw an error. Server Cache for accessing search parameters in deeply nested React Server Components without prop drilling, you can use createSearchParamsCache.

You define your parsers and then call .parse() in the root Server Component. Child Server Components can then access type-safe values using searchParamsCache.get('key')

End Notes

nuqs is a modern, elegant, and powerful solution for managing URL query parameters in the React ecosystem. It provides necessary features like type-safe server handling, batching, and universal adapter support, all while retaining a simple useState-like developer experience

If you are ready to simplify your URL state logic, installation is straightforward:

npm install nuqs

More from this blog

Nidhin's blog

168 posts

✨Crafting Code with a Smile for 8 Years:) Merging the Formal Dance of Angular, the Playful Rhythms of React, and the Next-level Moves of Next.js 🚀