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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@adaskothebeast/http-params-processor-react-tanstack-query

v12.0.0

Published

TanStack Query hooks and query options for React requests with deeply nested query parameter objects.

Readme

⚛️ @adaskothebeast/http-params-processor-react-tanstack-query

The TanStack Query adapter of HttpParamsProcessor: a useQuery hook that flattens nested params into the request URL for you.

npm license

No runtime dependency beyond core and TanStack Query; requests use the platform fetch. ESM only ("type": "module"). sideEffects: false.


📦 Install

npm i @adaskothebeast/http-params-processor-react-tanstack-query @adaskothebeast/http-params-processor-core

Peer dependencies: @adaskothebeast/http-params-processor-core ^12.0.0, @tanstack/react-query >=5.0.0.


🎯 What it does

useQueryWithParams builds the request URL from url + paramsKey + params, wires a GET fetcher, and derives the cache key from the same inputs:

url:      /api/users
queryKey: ['users', 'filter', { status: 'active' }]
request:  /api/users?filter.status=active

Everything else is plain TanStack Query, so staleTime, enabled, select, retry and friends still work.


🧰 API

| Export | Returns | Notes | | --------------------------------------------------------------- | ------------------------------- | -------------------------------------------------------- | | useQueryWithParams<TData, TError>(options) | UseQueryResult<TData, TError> | Hook; wraps useQuery | | createQueryOptionsWithParams<TData>(options) | queryOptions object | For prefetchQuery, ensureQueryData or sharing config | | buildUrlWithParams(url, paramsKey, params, processorOptions?) | string | The URL builder used internally | | getProcessedUrl(url, paramsKey, params, processorOptions?) | string | Alias of buildUrlWithParams, handy for debugging |

Options

UseQueryWithParamsOptions<TData, TError> extends UseQueryOptions with 'queryKey' | 'queryFn' omitted, and adds:

| Option | Type | Default | | ------------------ | ----------------------------- | ------------------- | | queryKey | QueryKey | required | | url | string | required | | paramsKey | string | required | | params | Record<string, unknown> | required | | processorOptions | QueryParamsProcessorOptions | core defaults | | fetchFn | typeof fetch | global fetch | | fetchOptions | RequestInit | { method: 'GET' } |

CreateQueryOptionsWithParamsOptions<TData> accepts exactly the same fields except the TanStack options (no staleTime, enabled, …).

QueryParamsProcessorOptions is { keyFormatter?, valueConverters? }.


⚡ Usage

import { useQueryWithParams } from '@adaskothebeast/http-params-processor-react-tanstack-query';

function Users() {
  const { data, isLoading, error } = useQueryWithParams<User[]>({
    queryKey: ['users'],
    url: '/api/users',
    paramsKey: 'filter',
    params: {
      status: 'active',
      roles: ['admin', 'user'],
      dateRange: {
        from: new Date('2024-01-01'),
        to: new Date('2024-12-31'),
      },
    },
    staleTime: 30_000,
  });

  if (isLoading) return <Spinner />;
  if (error) return <Error error={error} />;
  return <UserList users={data ?? []} />;
}

Prefetching or sharing configuration:

import { createQueryOptionsWithParams } from '@adaskothebeast/http-params-processor-react-tanstack-query';

await queryClient.prefetchQuery(
  createQueryOptionsWithParams<User[]>({
    queryKey: ['users'],
    url: '/api/users',
    paramsKey: 'filter',
    params: { status: 'active' },
  }),
);

Credentials, headers and a custom transport:

useQueryWithParams<User[]>({
  queryKey: ['users'],
  url: '/api/users',
  paramsKey: 'filter',
  params: { status: 'active' },
  fetchOptions: {
    headers: { Accept: 'application/json' },
    credentials: 'include',
  },
  fetchFn: myInstrumentedFetch,
});

🎛️ Options and configuration

import { BracketNotationKeyFormattingStrategy } from '@adaskothebeast/http-params-processor-key-bracket-notation';

useQueryWithParams<User[]>({
  queryKey: ['users'],
  url: '/api/users',
  paramsKey: 'filter',
  params: { user: { name: 'John' } },
  processorOptions: {
    keyFormatter: new BracketNotationKeyFormattingStrategy(),
  },
});
// /api/users?filter%5Buser%5D%5Bname%5D=John

processorOptions is per hook call; there is no provider or global registry here. A fresh ParamsProcessor is created inside buildUrlWithParams on every call, so the options object is the only place configuration lives.

Providing valueConverters replaces the core defaults, so include a Date converter if you still pass native dates.


📤 Output examples

buildUrlWithParams / getProcessedUrl results:

buildUrlWithParams('/api/users', 'filter', { status: 'active', count: 10 });
// /api/users?filter.status=active&filter.count=10

buildUrlWithParams('/api/users', 'filter', { user: { name: 'John', age: 30 } });
// /api/users?filter.user.name=John&filter.user.age=30

buildUrlWithParams('/api/users', 'filter', { roles: ['admin', 'user'] });
// /api/users?filter.roles%5B0%5D=admin&filter.roles%5B1%5D=user

buildUrlWithParams('/api/users', 'filter', {
  createdAt: new Date('2024-01-01T00:00:00.000Z'),
});
// /api/users?filter.createdAt=2024-01-01T00%3A00%3A00.000Z

buildUrlWithParams('/api/users?page=1', 'filter', { status: 'active' });
// /api/users?page=1&filter.status=active

buildUrlWithParams('/api/users', 'filter', { a: null, b: undefined });
// /api/users

The effective cache key is [...queryKey, paramsKey, params], for example ['users', 'filter', { status: 'active' }].


⚠️ Edge cases

  • The hook needs a QueryClientProvider above it, like any TanStack Query hook.
  • Query key stability comes from TanStack Query's structural hashing, not from object identity, so recreating the params literal on every render does not cause refetches. The trade-off: params must be hashable, so avoid functions or class instances that do not survive JSON.stringify inside it.
  • Because paramsKey and params are appended to your queryKey, two calls that differ only in params get separate cache entries automatically. Keep queryKey as the stable prefix (['users']).
  • Non-ok responses throw Error: HTTP error! status: <status>; the body is not read, so add your own error parsing through fetchFn if you need details.
  • The response is always parsed with response.json(). Endpoints that return 204 No Content or text will reject.
  • fetchOptions is spread after method: 'GET', so passing method there overrides the verb (the params still go in the query string, not the body).
  • enabled: false works as usual and prevents the request; there is no separate "skip" flag.
  • createQueryOptionsWithParams returns only queryKey and queryFn; spread extra TanStack options in yourself if you need them: { ...createQueryOptionsWithParams(...), staleTime: 60_000 }.
  • buildUrlWithParams returns the base URL unchanged when nothing is produced, and picks & over ? when the URL already contains a ?.
  • null/undefined params are skipped, $type is ignored, and circular references throw Error: Circular reference detected at key: <key> while the URL is being built.
  • Keys are encoded, so bracket characters appear as %5B/%5D in the final URL.

🔗 Related packages

Full matrix and recipes: main README.


📄 License

MIT © Adam Pluciński