npm.io
1.1.0 • Published 4 months ago

react-use-promise-raii

Licence
MIT
Version
1.1.0
Deps
0
Size
21 kB
Vulns
0
Weekly
0

react-use-promise-raii

NPM JavaScript Style Guide

React hooks that track in-flight promises with a shared counter, RAII style. Wrap a promise and the counter is incremented while it is pending and always decremented when it settles (resolve or reject) — useful for global loading overlays and input blocking.

Requires React 18 or 19.

Install

npm install --save react-use-promise-raii

API

Export Description
ProviderPromiseRaii Context provider that owns the pending counter.
useCheckPromiseRaii() Returns the current number of pending wrapped promises.
usePromiseRaii() Returns wrap(promise) — counts the promise while pending.
usePromiseRaiiSleep() Returns wrap(promise, ms = 100) — like usePromiseRaii, but holds the counter for at least ms (prevents spinner flicker).
usePromiseRaiiArray() Returns wrap(promises[]) — counts a whole Promise.all batch as one acquisition.

Without a ProviderPromiseRaii ancestor, the wrap hooks are no-ops and useCheckPromiseRaii always returns 0.

Usage

global blocking io : example1 + example2 + example3
  • example1: provider installation is required.
import { ProviderPromiseRaii } from "react-use-promise-raii";

export default function App() {
  return (
    <>
      <GlobalStyle />
      <ProviderPromiseRaii>
        <HomePage/>
      </ProviderPromiseRaii>
    </>
  );
}
  • example2: When you need global blocking...
import { useCheckPromiseRaii } from "react-use-promise-raii";

const useBlockingIoPreventKeyEvents = (isBlocking: boolean) => {
  useEffect(() => {
    if (!isBlocking) return;
    const keyEvents = ["keydown", "keypress", "keyup"];
    const onKeyEvent = (e: Event) => e.preventDefault();
    keyEvents.forEach((k) => document.addEventListener(k, onKeyEvent));
    return () => {
      keyEvents.forEach((k) => document.removeEventListener(k, onKeyEvent));
    };
  }, [isBlocking]);
};

export const BlockingIo = () => {
  const isBlocking = useCheckPromiseRaii() > 0; // useCheckPromiseRaii

  useBlockingIoPreventKeyEvents(isBlocking);

  return (
    <WrBlockingIo isBlocking={isBlocking}>
      <Watch visible={isBlocking} color={"#ffffff"} width={80} height={80} />
    </WrBlockingIo>
  );
};

const WrBlockingIo = styled.div<{ isBlocking: boolean }>`
  visibility: ${(props) => (props.isBlocking ? "visible" : "hidden")};

  z-index: ${zIndex.blocking};
  position: fixed;
  width: 100%;
  height: 100%;

  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
`;
  • example3: When you want to delay a promise.
import { usePromiseRaiiSleep } from "react-use-promise-raii";

export const useAxios = () => {
  const raiiSleep = usePromiseRaiiSleep();

  const axiosGet = useCallback(
    async (queryKey: string) => {
      if (queryKey.length === 0) return null;
      const { data } = await raiiSleep(axios.get(queryKey, axiosConfig), 1000);
      return data;
    },
    [raiiSleep]
  );

  // ...

  return {axiosGet, ... }
}

License

MIT eezz4

Keywords