npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

inertia-react-query-state

v1.0.2

Published

A library for managing query state in Inertia.js

Readme

inertia-react-query-state

npm version npm downloads license

Elegant query string state for Inertia.js + React, made for Laravel filters. Keep your filters in the URL, persist on reload, and navigate with real Inertia visits automatically.

Why

When filtering data in a Laravel app, you often want to:

  • pass filter values to the backend via query parameters
  • preserve filters on reload or when sharing a link
  • keep Inertia navigation and page state intact

This hook binds a piece of React state to a query-string key and triggers router.visit on change. On mount, it initializes from the current URL — you do NOT need to pass the default filter value from the backend. The URL is the single source of truth.

Requirements

  • React 18+
  • @inertiajs/react v2+ (peer dependency; ensure it exists in your project)

Install

yarn add inertia-react-query-state

Quick start

import useInertiaQueryState from "inertia-react-query-state"

export default function ProductsPage() {
  const [search, setSearch] = useInertiaQueryState<string>("search")

  return (
    <input
      value={search ?? ""}
      onChange={e => setSearch(e.target.value)}
      placeholder="Search products..."
    />
  )
}

Changing the input updates ?search= in the URL and performs an Inertia visit with preserveState: true and your provided options.

Laravel example

Controller (simplified):

// app/Http/Controllers/ProductController.php
use App\Models\Product;
use Inertia\Inertia;

public function index()
{
    $search = request('search');

    $products = Product::query()
        ->when($search, fn ($q) => $q->where('name', 'like', "%{$search}%"))
        ->latest()
        ->paginate(15)
        ->withQueryString(); // keep filters in pagination links

    return Inertia::render('Products/Index', [
        'products' => $products
    ]);
}

React page:

import useInertiaQueryState from "inertia-react-query-state"

export default function ProductsIndex({ products }) {
  const [search, setSearch] = useInertiaQueryState("search")

  // render products table ...
}

Multiple filters

Use one hook per query key:

const [status, setStatus] = useInertiaQueryState("status", { resetValue: "all" })
const [category, setCategory] = useInertiaQueryState("category")

Debouncing text input

const [raw, setRaw] = useState("")
const [search, setSearch] = useInertiaQueryState("search")

useEffect(() => {
  const id = setTimeout(() => setSearch(raw), 300)
  return () => clearTimeout(id)
}, [raw])

Default value behavior

  • On mount, the hook reads from the URL and uses that value if present.
  • If the URL has no value for the key, defaultValue (if provided) is used as the initial state.
  • defaultValue is for when you want to start with a specific value even when the URL is empty — you do not need to pass defaults from Laravel.

API

const [value, setValue] = useInertiaQueryState<T>(key: string, options?: {
  defaultValue?: T
  resetValue?: string
  // Any VisitOptions from @inertiajs/core except `preserveState` (always true)
  // Examples: replace, only, onSuccess, onError, data, etc.
}): readonly [T | undefined, React.Dispatch<React.SetStateAction<T | undefined>>]

Options

  • defaultValue: Initial value when the URL has no value for the key. Use when you want the filter to start with a specific value on first render. Once the user changes it, the URL becomes the source of truth.
  • resetValue: If the state equals this string, the query parameter is removed from the URL. Useful for sentinel values like "all" or "none" to mean "no filter applied".
  • VisitOptions passthrough: Any VisitOptions from @inertiajs/core (except preserveState, which is always true) are forwarded to router.visit. Useful when you need to customize the visit:
    • only: Request only specific props from the server to optimize payloads
    • data: Send additional data with the visit
    • headers: Add custom headers
    • onSuccess / onError / onFinish: Lifecycle callbacks
    • replace: Replace the current history entry instead of pushing a new one. Optional; helpful if you don't want a new history entry for each filter keystroke. You do not need to pass this for normal usage.

Notes

  • Values are written to the URL as strings and read back as strings; use T = string or convert as needed.
  • preserveState is forced to true so your page component tree stays stable across visits.
  • Works on the client (browser) – this hook reads window.location.

Scripts

yarn build
yarn test

License

MIT