Skip to content

Instantly share code, notes, and snippets.

@kapobajza
Last active April 28, 2021 19:56
Show Gist options
  • Save kapobajza/b0676c7c2a4a219382a7dcd7b2aae317 to your computer and use it in GitHub Desktop.
Save kapobajza/b0676c7c2a4a219382a7dcd7b2aae317 to your computer and use it in GitHub Desktop.
type ActionHandler = (...args: any[]) => Promise<(() => void) | undefined | void>;
// Hook used to initiate loading on action started and finish loading on action completed
const useLoading = (action: ActionHandler, timeout = 0): [ActionHandler, boolean] => {
const [loading, setLoading] = useState(false);
const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);
const doAction: ActionHandler = (...args: any[]) => {
setLoading(true);
return action(...args).finally(() => {
setTimeout(() => {
// Call setLoading only if the component is mounted, otherwise we'll get a memory leak
if (isMounted.current) {
setLoading(false);
}
}, timeout); // Set a short timeout, which is needed when the component needs to unmount succesfully
});
};
return [doAction, loading];
};
// Example usage:
// const doAction = async () => {
// try {
// await apiCall();
// } catch (err) {
// console.error(err);
// }
// };
// const [onButtonPress, loading] = useLoading(doAction);
// return (
// <div>
// <button onClick={onButtonPress}>Start loading</button>
// {loading ? <p>Loading...</p> : null}
// </div>
// );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment