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

@scality/react-chained-query

v2.0.1

Published

A wrapper of react-query useQuery hook allowing chained queries.

Readme

react-chained-query

Features

useChainedQuery

useChainedQuery hook consit of a wrapper on top of react-query useQuery. This useChainedQuery hook allow chaining queries instead of runnning them concurently, it aims to solve problems that may occurs when hitting a slow backend with too many requests.

By managing a queue and executing the request one after another, it could give the capability for an application to display the information sequentially.

useChainedMutations

useChainedMutations hook chains mutations sequentially with retry support. It supports both static (pre-created) and dynamic (hook-based) mutations. Each step receives results from previous mutations to compute its variables.

Install

npm install @scality/react-chained-query

Quickstart

useChainedQuery

import { QueryClient, QueryClientProvider } from 'react-query';
import { ChainedQueryProvider, useChainedQuery } from '@scality/react-chained-query';

const queryClient = new QueryClient();

function Component1() {
  const { data } = useChainedQuery({
    queryKey: ['key', 'arg'],
    queryFn: async () => {
      await new Promise((resolve) => setTimeout(resolve, 2_000));
      return '1';
    },
  });
  return <>{data}</>;
}

function Component2() {
  const { data } = useChainedQuery({
    queryKey: ['key', 'arg1'],
    queryFn: async () => {
      await new Promise((resolve) => setTimeout(resolve, 1_000));
      return '2';
    },
  });
  return <>{data}</>;
}

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <ChainedQueryProvider>
        <div className="App">
          <h2>Hello, useChainedQuery! </h2>
          <Component1 />
          <Component2 />
        </div>
      </ChainedQueryProvider>
    </QueryClientProvider>
  );
}

A complete example here

useChainedMutations

Basic Usage (Static Mutations)

import { useMutation } from 'react-query';
import { useChainedMutations } from '@scality/react-chained-query';

const useUpdatePost = () => {
  return useMutation({
    mutationFn: async (id: string) => {
      const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`, {
        method: 'PUT',
        headers: { 'Content-type': 'application/json' },
        body: JSON.stringify({ id, title: 'foo', body: 'bar', userId: id }),
      });
      if (!res.ok) throw res.statusText;
      return res.json();
    },
  });
};

export default function App() {
  const updateUser1 = useUpdatePost();
  const updateUser2 = useUpdatePost();

  const { steps, isComplete, hasError, start } = useChainedMutations({
    mutations: [
      { id: 'user1', label: 'Update User 1', mutation: updateUser1 },
      { id: 'user2', label: 'Update User 2', mutation: updateUser2 },
    ],
    variables: {
      user1: () => '1',
      user2: (prev) => prev.user1.data.userId, // Access by key (recommended)
      // Or: (prev) => prev[0].data.userId    // Access by index (still supported)
    },
    autoStart: false,
  });

  return (
    <div>
      <button onClick={start}>Start</button>
      <ul>
        {steps.map((step) => (
          <li key={step.id}>
            {step.label}: {step.status}
            {step.status === 'error' && <button onClick={step.retry}>Retry</button>}
          </li>
        ))}
      </ul>
      {isComplete && <p>Done!</p>}
      {hasError && <p>Error occurred</p>}
    </div>
  );
}

Dynamic Mutations (for dynamic lists)

When you need to create mutations from a dynamic array (e.g., user-selected items), use hook instead of mutation:

const userIds = ['1', '2', '3']; // Could come from props or state

const { Slots, steps, start } = useChainedMutations({
  mutations: userIds.map((id) => ({
    id: `user-${id}`,
    label: `Update User ${id}`,
    hook: useUpdatePost, // Hook will be called internally for each mutation
  })),
  variables: Object.fromEntries(
    userIds.map((id, i) => [`user-${id}`, (prev) => (i === 0 ? id : prev[i - 1].data.userId)])
  ),
});

return (
  <>
    {Slots} {/* Required: renders hidden components that call hooks for dynamic mutations */}
    <button onClick={start}>Start</button>
  </>
);

API

| Config | Type | Description | |--------|------|-------------| | mutations | MutationConfig[] | Array with id, label, and either mutation (static) or hook (dynamic) | | variables | Record<string, (prev) => unknown> | Functions to compute variables. Access results via prev.mutationId.data (recommended) or prev[i].data. Note: Mutation ids should not be numeric strings ("0", "1") or array method names ("length", "push", "map", etc.) as they conflict with array properties. | | autoStart | boolean | Auto-start when ready. Default: true |

| Return | Type | Description | |--------|------|-------------| | Slots | ReactNode | Render this for dynamic mutations | | steps | StepStatus[] | { id, label, step, status, retry } | | isReady | boolean | All mutations registered | | isComplete | boolean | All succeeded | | hasError | boolean | Any failed | | start | () => void | Manual start | | reset | () => void | Reset chain state, allows start() again | | getResult | <T>(id: string) => T | Get mutation result |

Advanced Documentation

In order to use useChainedQuery in your component, it has be below QueryClientProvider and ChainedQueryProvider.

It's possibile to have several ChainedQueryProvider each of them would then holds it's own queue of queries.

<QueryClientProvider>
  <ChainedQueryProvider>
    <YourComponent />
  </ChainedQueryProvider>
</QueryClientProvider>

Made with ❤️ by Pod-UI at Scality