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 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-query-factory

v0.1.0

Published

Create API client for your React app with just one line of code, using React Query!

Downloads

262

Readme

React Query Factory Documentation

Introduction

The react-query-factory library provides a streamlined and type-safe approach to organizing your API layer in React applications when using TanStack's React Query. By simply providing a "service" object to the createQueriesFromService function, developers can generate a fully typesafe queries object, reducing boilerplate and enhancing code clarity and maintainability.

Getting Started

Installation

To begin using react-query-factory, you must first ensure that @tanstack/react-query is installed and set up in your project as it is a peer dependency. If not, you can install it using npm or yarn:

npm install @tanstack/react-query

or

yarn add @tanstack/react-query

Once React Query is installed, you can proceed to install react-query-factory:

npm install react-query-factory

or

yarn add react-query-factory

Basic Usage

  1. Define a Service Object: Start by defining a service object that includes methods for your API calls. Each method should return a promise resolving to the data you wish to fetch or mutate.

    // Example service object
    const productService = {
      async getProducts(): Promise<Product[]> {
        // Implementation for fetching products
      },
      async getProductById(id: string): Promise<Product> {
        // Implementation for fetching a single product by ID
      },
      async createProduct(productData: Omit<Partial<Product>, 'id'>): Promise<Product> {
        // Implementation for creating a new product
      },
    };
  2. Generate Queries and Mutations: Use createQueriesFromService to generate query and mutation hooks from your service object.

    import { createQueriesFromService } from 'react-query-factory';
    
    const queries = createQueriesFromService(productService, 'products');

    Besides a service object createQueriesFromService, accepts queryKeyPrefix as a second argument. This is required so we can automatically generate queryKey for every query.

  3. Use Generated Hooks in Components: You can now use the generated query and mutation hooks in your components.

    import React from 'react';
    
    const ProductList = () => {
      const { data, isLoading, error } = queries.getProducts.useQuery();
      const { mutate } = queries.createProduct.useMutation();
    
      if (isLoading) return <div>Loading...</div>;
      if (error) return <div>An error occurred: {error.message}</div>;
    
      return (
        <ul>
          {data?.map(product => (
            <li key={product.id}>{product.name}</li>
          ))}
        </ul>
      );
    };

Generating Query Keys with react-query-factory

With react-query-factory, query keys are generated automatically based on the service method names and parameters. Keys are coupled to queries itself so you don't have to manage them at all.

Default Query Keys

By default, createQueriesFromService generates query keys using the following pattern:

[queryKeyPrefix, methodName, ...methodParams];
  • queryKeyPrefix: A string you provide when generating queries and mutations, acting as a namespace for your keys.
  • methodName: The name of the service method used for the query or mutation.
  • methodParams: Parameters passed to the query or mutation, ensuring uniqueness for different parameter values.

Example: Using Query Keys

Consider a scenario where you have a query to fetch a product by its ID. The query key might be generated as follows:

const productQueryKey = queries.products.getById.queryKey({ id: '2' });

This generates a query key like ['products', 'getById', { id: '2' }], uniquely identifying the query within the React Query cache.

Utilizing Query Keys in Components

Query keys can be used directly in your components for various purposes, such as manually invalidating or refetching queries. Here's an example of how you might use a query key in a component:

function Index() {
  const queryClient = useQueryClient();

  const product = queryClient.getQueryData(queries.products.getById.queryKey({ id: '2' }));

  return <div>{/* Render your product details */}</div>;
}

In this example, queries.products.getById.queryKey({ id: '2' }) generates the query key used to fetch the product details. This key can also be used for cache management tasks, such as invalidating the query to force a refetch if the product data changes.

Understanding and using query keys effectively allows you to manage and optimize the caching behavior of your queries and mutations, ensuring your application remains fast, responsive, and efficient.

Advanced Usage

Handling Parameters

For service methods that require parameters, react-query-factory automatically generates hooks that accept these parameters and include them in the query key to ensure correct caching and invalidation. All cases are covered.

useQuery without params

If your service function doesn't accept params, you are able to pass options to the useQuery like normal. With the exception of queryKey and queryFn params.

const { data } = queries.products.getAll.useQuery();
//or
const { data } = queries.products.getAll.useQuery({
    enabled: true,
    refetchInterval: 6000,
    ...
  });

useQuery with params

If your service function accepts params, you are able to pass params and options arguments to the useQuery hook.

const { data } = queries.products.getById.useQuery({id: "123"});
//or
const { data } = queries.products.getById.useQuery({id: "123"}, {
    enabled: true,
    refetchInterval: 6000,
    ...
  });
//or if params are optional but you still want to pass options
const { data } = queries.products.getById.useQuery(undefined, {
    enabled: true,
    refetchInterval: 6000,
    ...
  });

useMutation without params

If your service function doesn't accept params, you are still able to pass options argument:

const { mutate } = queries.products.createProduct.useMutation();
//or
const { mutate } = queries.products.createProduct.useMutation({ onSuccess: () => alert('on mutation success') });

mutate(); // doesn't require any params, no TS error

useMutation with params

If your service function accepts params, you are able to pass params to mutate function and options arguments to the useMutation hook.

const { mutate } = queries.products.createProduct.useMutation();
mutate({name: "iPhone pro", image: "xyz.com/img.jpg", ... })
mutate() // Will throw TS error
//or
const { mutate } = queries.products.createProduct.useMutation({ enabled: false, ... });

Centralized API layer

It's suggested that you have one object which encapsulates all of the queries. For example:

const postsService = { getPosts, createPosts, getPostById };
const productService = { getProducts, addProductToCard, getProductById };
const postsQueries = createQueriesFromService(postsService, "posts");
const productsQueries = createQueriesFromService(productService, "products");

const queries = { posts: postsQueries, products: productsQueries };

const Foo = () => {
	const { data } = queries.products.getProducts.useQuery()
	...
}

This way your API layer is centralized in queries object, so next developer doesn’t have to second guess names like productService, since they can rely on autocomplete to offer them suggestions by typing queries..

Type Safety

react-query-factory leverages TypeScript for full type safety, ensuring that your service methods, parameters, and return types are correctly typed. This reduces runtime errors and improves the developer experience.

Contributing

Contributions to react-query-factory are welcome. Whether it's feature requests, bug reports, or pull requests, your input helps make this library better for everyone.

License

react-query-factory is open-source software licensed under the MIT license.