Skip to content

Instantly share code, notes, and snippets.

@abonello
Forked from codemile/useSafeState.tsx
Created December 30, 2021 20:18
Show Gist options
  • Save abonello/0089cda311be5face320a23531799681 to your computer and use it in GitHub Desktop.
Save abonello/0089cda311be5face320a23531799681 to your computer and use it in GitHub Desktop.
Here is a useSafeState hook that ignores state changes after a component has been unmounted.
import {
DependencyList,
Dispatch,
MutableRefObject,
SetStateAction,
useCallback,
useEffect,
useRef,
useState
} from 'react';
/**
* Returns a ref that indicates if the component has unmounted.
*/
export const useUnmounted = (): MutableRefObject<boolean> => {
const ref = useRef<boolean>(false);
useEffect(() => () => (ref.current = true), []);
return ref;
};
/**
* Returns a callback that only executes if the component is mounted.
*/
export const useSafeCallback = <T extends (...args: any[]) => any>(
callback: T,
deps: DependencyList
) => {
const unmounted = useUnmounted();
return useCallback(
(...args) => {
if (!unmounted.current && callback) {
callback(...args);
}
},
[callback, ...deps]
);
};
/**
* Returns a state hook that can safely be used after component is unmounted.
*/
export const useSafeState = <S,>(
initialState: S | (() => S)
): [S, Dispatch<SetStateAction<S>>] => {
const [value, setValue] = useState(initialState);
const safeValue = useSafeCallback(setValue, []);
return [value, safeValue];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment