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

@zoos/react-query

v1.13.2

Published

A simple utility for creating mutation and query options with type inference and other quality of life improvements.

Downloads

562

Readme

@zoos/react-query

A simple utility for creating mutation and query options with type inference and other quality of life improvements.

Core principles

  • Define the important parts of queries / mutations and let the caller define the rest
  • Types should be inferred based on queryFn or mutationFn

Installation

npm install @zoohilldata/react-query

Use

For more details, view examples in React Query Demo

createQueryOptions

import { useQuery } from "@tanstack/react-query";
import { createQueryOptions } from "@zoohilldata/react-query";

///
/// Define `getQueryOptions`
///

// Type inference based on queryFn
const getQueryOptions = queryOptions({
  queryKey: ["my-query"],
  queryFn: async (params: { id: number }) => {
    const data = await getDataFn();

    if (!data) {
      throw new Error("Data not found");
    }

    return data;
  },
  options: {
    refetchInterval: 2000,
  },
});

///
/// Use in component
///

const App = () => {
  const { data } = useQuery(
    // Override the refetch interval for this specific query
    getQueryOptions({ params: { id: 1 }, options: { refetchInterval: 3000 } }),
  );

  //
  // ...
  //
};

createMutationOptions

import { useMutation } from "@tanstack/react-query";
import { createMutationOptions } from "@zoohilldata/react-query";

///
/// Define the mutation
///

const getMutationOptions = createMutationOptions({
  mutationKey: ["my-mutation"],
  mutationFn: async (variables: { id: number }) => {
    const data = await postDataFn(variables);

    if (!data) {
      throw new Error("Data not found");
    }

    return data;
  },
  options: {
    onSuccess: ({ data, variables, queryClient }) => {
      // Do things on success in the standard definition
      // mostly for query cache invalidation at this stage.
      //
      // We typically let the caller handle specific onSuccess
      // handlers like showing a toast
      queryClient.invalidateQueries({ queryKey: ["my-query"] });
    },
  },
});

///
/// Use in component
///

import { Button } from "@zoohilldata/ui";

const App = () => {
  // Get the query client to pass to the `getMutationOptions` function.
  //
  // If using `@tanstack/react-router-with-query` and passing queryClient
  // through route context (preferred), use:
  // const { queryClient } = Route.useRouterContext()
  const queryClient = useQueryClient();

  const { mutate } = useMutation({
    options: {
      onSuccess: ({ queryClient, data, variables }) => {
        window.alert(`Success: ${JSON.stringify({ data, variables })}`);
      },
    },
  });

  return <Button onClick={() => mutate({ id: 1 })}>Run Mutation</Button>;
};

Gotchas - passing empty params / variables

When calling a mutationFn or initializing a query with getQueryOptions, you must pass params into getQueryOptions and variables into mutate() function even if they are not required in your queryFn / mutationFn.

E.g.,

const getQueryOptions = queryOptions({
  queryKey: ["my-key"],
  // Query function does not require parameters
  queryFn: async () => doSomething(),
});

const App = () => {
  const { data } = useQuery(
    // Params must be passed even if not required in queryFn definition above.
    // it doesn't matter what you pass b/c params have type `unknown`, but {} is the convention
    getQueryoptions({
      params: {},
    }),
  );
};

Why?

The types don't flow through properly in this situation with the current implementation. We would like to fix this in a future release so you can call getQueryOptions() and mutate() without passing empty params / variables