Imagine a hook:
export function useMounted() {
const mounted = React.useRef<boolean>(false);
React.useEffect(() => {
mounted.current = true;
return () => {
mounted.current = false;
};
}, []);
return mounted;
}
I'd like to use that hook to determine whether component is still mounted or not. One use case for it is to asynchronously load image and display image only when browser has fetched and cached it. Simplified version of such use case can be:
function useLazyImage(src: string, triggerCallback: any) {
const mounted = useMounted();
const image = useRef<HTMLImageElement>();
useEffect(() => {
if (!!src) {
image.current = new Image();
image.current.onload = () => {
if (mounted.current)
triggerCallback();
};
image.current.src = src;
return () => {
image.current = undefined;
};
}
return undefined;
}, [src]);
}
It doesn't include error handling and doesn't handle changes of triggerCallback but it shows my problem. react-hooks/exhaustive-deps warns me about missing mounted dependency even though it shouldn't afaik. Since mounted is Ref, by using it I don't accidentally close over stale scope and eslint in fact knows this. If I change my code to
function useLazyImage(src: string, triggerCallback: any) {
const mounted = React.useRef<boolean>(false);
React.useEffect(() => {
mounted.current = true;
return () => {
mounted.current = false;
};
}, []);
const image = useRef<HTMLImageElement>();
eslint doesn't warn me anymore. Is this limitation of ESLint that it can't know what a result of my custom hook is or I'm doing this incorrectly and there's a bug lurking?