Skip to content

Instantly share code, notes, and snippets.

@eneko89
Last active October 27, 2022 17:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eneko89/4a5a44eabe403f1152be961c776b80fa to your computer and use it in GitHub Desktop.
Save eneko89/4a5a44eabe403f1152be961c776b80fa to your computer and use it in GitHub Desktop.
Custom hook for that provides an "ignore" object to avoid race conditions or memory leaks in async operations
import { useEffect } from 'react';
type EffectReturn = Promise<(() => void) | void>;
type EffectFunction = (ignore: { current: boolean }) => EffectReturn;
type DependencyArray = unknown[];
/**
* Works like useEffect, but accepts an async function as the effect
* function and provides an ignore object with a current attribute
* that tells if you should ignore the result.
*
* From React Hooks API reference: "If a component renders multiple
* times (as they typically do), the previous effect is cleaned up
* before executing the next effect"
*
* useAsyncEffect(async (ignore) => {
* const result = await asyncOperation();
*
* if (!ignore.current) {
* setResult(result);
* }
* }, []);
*/
function useAsyncEffect(
effectFunction: EffectFunction,
dependencyArray: DependencyArray,
): void {
/* eslint-disable react-hooks/exhaustive-deps */
useEffect(() => {
const ignore = { current: true };
const result = effectFunction(ignore);
return () => {
ignore.current = false;
(async () => {
const cleanupFunction = await result;
if (typeof cleanupFunction === 'function') {
cleanupFunction();
}
})();
};
}, dependencyArray);
/* eslint-enable react-hooks/exhaustive-deps */
}
export default useAsyncEffect;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment