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

usable-query

v0.0.6

Published

UsableQuery simplifies the use of React Query by offering a streamlined and centralized approach to managing queries and mutations. Designed for developers who seek efficiency and ease in their React applications, this package enables quick setup, intuiti

Downloads

13

Readme

Usable Query: Simplifying React Query Management

View on CodeSandbox

npm

NPM

⚡️About

UsableQuery, is a React utility package designed to enhance the experience of working with the React Query library. It provides a streamlined and centralized approach for managing queries and mutations, making data fetching and state management in React applications both efficient and intuitive. Built with the needs of modern web developers in mind, UsableQuery aims to reduce boilerplate, improve readability, and accelerate the development process in React-based projects.

✨ Features

  • 📦 Centralized Query Management
  • 🔧 Simplified Query Syntax
  • ✅ Efficient Data Fetching
  • ⚒ CommonJS, ESM & browser standalone support
  • 📚 Extensive Documentation
  • 👍🏾 Listener Configurations
  • 📝 TypeScript Support

⬇ Installing usable-query

[!IMPORTANT] @tanstack/react-query is a peer dependency of usable-query, so you must install it in your project before installing usable-query.

Using NPM

npm i @tanstack/react-query 

npm i usable-query

Using Yarn

yarn add @tanstack/react-query

yarn add usable-query

Using CDN

<!-- React Query -->
<script src="https://cdn.skypack.dev/@tanstack/react-query"></script>

<!-- Usable Query -->
<script src="https://cdn.skypack.dev/usable-query"></script>

📖 Getting Started

This guide will walk you through the process of installing and implementing UsableQuery in your React project.

Prerequisites

Before you begin, ensure that you have the following installed:

  • Node.js (version 14 or later)
  • npm (usually comes with Node.js) or Yarn
  • A React project set up and ready to go
  • UsableQuery is built to work alongside React Query, so you should also have @tanstack/react-query installed in your project.

Setting Up

View on CodeSandbox

After installing, you can set up UsableQuery in your project. Here's a basic example to get you started, first we need to setup our base UsableQuery instance:

File: u-api-query.ts

import { buildApi } from 'usable-query';
import { QueryClient } from '@tanstack/react-query'; // or your already configured query client


const cacheTime = 1000 * 60 * 60 * 24; // 24 hours

export const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      cacheTime,
      staleTime: cacheTime,
      refetchOnWindowFocus: false,
    },
  },
});


export const baseUQuery = buildApi({
  baseUrl: 'https://jsonplaceholder.typicode.com',
  queryClient,
});

After this we can now use our baseUQuery instance to create our first query or mutation.:

File: api/user.ts

import { baseUQuery } from './u-api-query';

type User = {
  id: number;
  name: string;
};

const userUQuery = baseUQuery.createUsableQuery({
  key: 'getUsers',
  endpoints: (builder) => ({
    getUsers: builder.query<null, User[]>({
      key: 'getUsers',
      queryFn: () => ({
        url: '/users',
        method: 'GET',
      }),
    }),
  }),
});

export const { useGetUsersQuery } = userUQuery; // export the generated hook and also the generated query function for server calls

File: App.tsx

import { useGetUsersQuery } from './api/user';

function App() {
  const { data, isLoading, error } = useGetUsersQuery();

  if (isLoading) return <div>Loading...</div>;

  if (error) return <div>Oops! Something went wrong...</div>;

  return (
    <div>
      {data?.map((user) => (
        <div key={user.id}>{user.name}</div>
      ))}
    </div>
  );
}

You see how easy it is to get started with UsableQuery? You can now start building your application with UsableQuery.

📚 Documentation

buildApi

The buildApi function is used to create a base UsableQuery instance. It takes in an object with the following properties:

| Property | Type | Description | | --- | --- | --- | | baseUrl | string | The base url for all requests made with this instance. | | queryClient | QueryClient | The query client instance to be used by this instance. | | baseQueryFn | BaseQueryFn | An optional function that can be used to override the default queryFn for all queries created with this instance. | | inject | BaseInject | An optional object containing functions that can be used to inject data into the query client cache. | | transformResponse | BaseTransformResponse | An optional function that can be used to transform the response of all queries created with this instance. |

Returns

  • createUsableQuery - A function that can be used to create queries and mutations with this instance.

createUsableQuery

The createUsableQuery function is used to create queries and mutations. It takes in an object with the following properties:

| Property | Type | Description | | --- | --- | --- | | key | string | The key for this query or mutation. | | endpoints | Endpoints | A function that returns an object containing the endpoints for this query or mutation. | | setup | {queryClient: QueryClient;baseQueryFn: any;} | An optional function that can be used to override the default queryFn for all queries created with this instance. |

Returns

  • use{key}Query - A hook that can be used to fetch data for this query or mutation.
  • {key} - A function that can be used to fetch data for this query or mutation.
  • use{key}Mutation - A hook that can be used to mutate data for this query or mutation.
  • {key}Mutation - A function that can be used to mutate data for this query or mutation.
  • startListening - A function that can be used to start listening for changes to the query or mutation.
  • stopListening - A function that can be used to stop listening for changes to the query or mutation.

Example

import { baseUQuery } from './u-api-query';

type User = {
  id: number;
  name: string;
};

const userUQuery = baseUQuery.createUsableQuery({
  key: 'getUsers',
  endpoints: (builder) => ({
    getUsers: builder.query<null, User[]>({
      key: 'getUsers',
      queryFn: () => ({
        url: '/users',
        method: 'GET',
      }),
    }),
  }),
});

userUQuery.startListening({
  matches: (action) => ['getUsers'].includes(action.key),
  performAction: async (action: function) => {
    // perform action
  },
}); // start listening for changes to the query or mutation

userUQuery.stopListening({
  matches: (action) => ['getUsers'].includes(action.key),
}); // stop listening for changes to the query or mutation

export const { useGetUsersQuery } = userUQuery; // export the generated hook and also the generated query function for server calls

Endpoints

The Endpoints type is an object containing the endpoints for a query or mutation. It takes in an object with the following properties:

| Property | Type | Description | | --- | --- | --- | | query | QueryEndpoint | An optional function that returns an object containing the query endpoint for this query or mutation. | | mutation | MutationEndpoint | An optional function that returns an object containing the mutation endpoint for this query or mutation. |

builder.query

The builder.query function is used to create a query endpoint. It takes in an object with the following properties:

| Property | Type | Description | | --- | --- | --- | | key | string | The key for this query or mutation. | | queryFn | QueryFn | The queryFn for this query or mutation. | | isInfinite | boolean | An optional boolean that can be used to indicate whether this query is infinite. | | transformResponse | TransformResponse | An optional function that can be used to transform the response of this query or mutation. |

Example

import { baseUQuery } from './u-api-query';

type User = {
  id: number;
  name: string;
};

const userUQuery = baseUQuery.createUsableQuery({
  key: 'getUsers',
  endpoints: (builder) => ({
    getUsers: builder.query<null, User[]>({
      key: 'getUsers',
      queryFn: () => ({
        url: '/users',
        method: 'GET',
      }),
    }),
  }),
  isInfinite: true,
  transformResponse: (response) => response.data,
});

export const { useGetUsersQuery } = userUQuery; // export the generated hook and also the generated query function for server calls

builder.mutation

The builder.mutation function is used to create a mutation endpoint. It takes in an object with the following properties:

| Property | Type | Description | | --- | --- | --- | | key | string | The key for this query or mutation. | | mutationFn | MutationFn | The mutationFn for this query or mutation. | | invalidatesQueries | string[] | An optional array of keys for queries that should be invalidated when this mutation is performed. | | setCache | SetCache | An optional function that can be used to set the cache for this mutation. |

Example


import { baseUQuery } from './u-api-query';

type User = {
  id: number;
  name: string;
};


const userUQuery = baseUQuery.createUsableQuery({
  key: 'getUsers',
  endpoints: (builder) => ({
    getUsers: builder.query<null, User[]>({
      key: 'getUsers',
      queryFn: () => ({
        url: '/users',
        method: 'GET',
      }),
    }),
    createUser: builder.mutation<null, User>({
      key: 'createUser',
      mutationFn: (user) => ({
        url: '/users',
        method: 'POST',
        body: user,
      }),
      invalidatesQueries: ['getUsers'],
      setCache: (cache, { data }) => {
        cache.setQueryData('getUsers', (old) => [...old, data]);
      },
    }),
  }),
});

export const { useGetUsersQuery, useCreateUserMutation } = userUQuery; // export the generated hook and also the generated query function for server calls

🤨 Motivation

The Challenge in Managing Data Fetching in React

While React Query is a powerful tool for managing server state, it can be challenging to work with, especially for developers new to the library or those working on large-scale projects. The syntax for defining and using queries and mutations can be confusing and difficult to read, and the process of setting up and managing server state can be tedious and time-consuming. This can lead to a lot of boilerplate code and make it difficult to maintain and scale React applications.

Why UsableQuery?

UsableQuery was born out of a need to simplify and streamline the process of working with queries and mutations in React applications. While React Query itself is a powerful tool for managing server state, I recognized that there could be a more intuitive and efficient way to handle these data fetching mechanisms, especially for developers new to the library or those working on large-scale projects.

My Goals

  • Simplify Query Syntax: Provide a more straightforward and readable syntax for defining and using queries and mutations, making it easier for developers of all levels to work with data fetching in React.

  • Centralize Query Management: Offers a centralized system to manage all queries and mutations, reducing boilerplate and improving maintainability. see this for more details.

  • Enhance Code Quality: Encourage better coding practices and architecture by providing a structured and consistent way to handle data fetching and state management.

  • Facilitate Easy Integration and Extensibility: Ensure that UsableQuery seamlessly integrates with existing React Query setups and is flexible enough to adapt to various use cases and requirements.

📝 License

This project is licensed under the MIT License - see the LICENSE file for details.