react-use-promise-raii
v1.1.0
Published
React hooks that track in-flight promises with a global counter, RAII style — for global loading indicators and input blocking
Downloads
233
Maintainers
Readme
react-use-promise-raii
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-raiiAPI
| 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
