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

@t8/react-pending

v1.0.31

Published

A concise async action state management lib for React apps

Readme

T8 React Pending

A concise async action state management lib for React apps

npm Lightweight CSR ✓ SSR ✓

Why? To manage the async action state, whether local or shared, without tightly coupling it with the app state. Decoupled pending state as described here acts like a lightweight scaffolding on top of the action's and component's successful scenario. It's easy to set up from scratch without rewriting the async actions and affecting the app state, and easy to manage further on since it's barely intertwined with other app's internals.

Installation: npm i @t8/react-pending

Shared pending state

Objective: Track the pending state of the asynchronous action fetchItems() to tell the user whether the UI is busy handling the async action or encountered an error, without rewriting the action and the app's state management.

In our setup, there are two components rendering their content with regard to the current state of fetchItems(), so the pending state is shared between these components:

+ import { usePendingState } from "@t8/react-pending";

  export let ItemList = () => {
    let [items, setItems] = useState([]);
+   let [state, withState] = usePendingState("fetch-items");

    useEffect(() => {
-     fetchItems().then(setItems);
+     withState(fetchItems()).then(setItems);
    }, [fetchItems, withState]);

+   if (!state.complete) return <p>Loading...</p>;
+   if (state.error) return <p>An error occurred</p>;

    return <ul>{items.map(/* ... */)}</ul>;
  };
+ import { usePendingState } from "@t8/react-pending";

  export let Status = () => {
+   let [state] = usePendingState("fetch-items");

    if (!state.initialized) return "";
    if (!state.complete) return "Busy";
    if (state.error) return "Error";

    return "OK";
  };

Live demo

⬥ To share the async action's pending state with multiple components we're using the string key parameter of usePendingState(stateKey). This key can be used with usePendingState(stateKey) in other components to refer to the same pending state (as in the Status component above), so stateKey should be unique to the particular pending state.

⬥ In the example above, the data returned from the async action is stored in the component's local state, but it can be stored in any app state of the developer's choice without affecting how the usePendingState() hook is used.

Local pending state

Omit the custom string key parameter of usePendingState() to scope the pending state locally within a single component:

- let [state, withState] = usePendingState("fetch-items"); // shared
+ let [state, withState] = usePendingState(); // local

Silent tracking of background actions and optimistic updates

- withState(fetchItems())
+ withState(fetchItems(), { silent: true })

⬥ This option prevents state.complete from switching to false in the pending state.

Delayed pending state

- withState(fetchItems())
+ withState(fetchItems(), { delay: 500 }) // in milliseconds

⬥ Use case: avoiding flashing a process indicator when the action is likely to complete by the end of a short delay.

Custom rejection handler

- withState(fetchItems())
+ withState(fetchItems(), { throws: true }).catch(handleError)

⬥ This option allows the async action to reject explicitly, along with exposing state.error that goes by default.

Providing blank initial pending state

+ import { PendingStateProvider } from "@t8/react-pending";

- <App/>
+ <PendingStateProvider>
+   <App/>
+ </PendingStateProvider>

<PendingStateProvider> creates an isolated instance of initial shared action state. Its prime use cases are SSR and tests. It isn't required with client-side rendering, but it can be used to separate action states of larger self-contained portions of an app.

Providing custom initial pending state

+ let initialState = {
+   "fetch-items": { initialized: true, complete: true },
+ };

- <PendingStateProvider>
+ <PendingStateProvider value={initialState}>
    <App/>
  </PendingStateProvider>

⬥ While fully optional, this setup allows to redefine the initial state received from usePendingState(stateKey).

⬥ With an explicit value or without, the <PendingStateProvider>'s nested components will only respond to updates in the particular action states they subscribed to by means of usePendingState(stateKey).