I have this custom react hook copied more of less straight from this dev.to article for use of the IntersecionObserver
in React. article here
The Hook
import { useEffect, useRef, useState } from "react"
export const useIntersectionObserver = (options) => {
const containerRef = useRef(null)
const [isVisible, setIsVisible] = useState(false)
const callback = (entries) => {
const [entry] = entries
setIsVisible(entry.isIntersecting)
}
useEffect(() => {
let currentEl;
const observer = new IntersectionObserver(callback, options);
if (containerRef && containerRef.current) {
currentEl = containerRef.current;
observer.observe(currentEl);
}
return () => {
if (containerRef && containerRef.current) {
currentEl = containerRef.current;
observer.unobserve(currentEl);
}
}
}, [containerRef, options])
return [containerRef, isVisible]
}
in my console I have this warning,
The ref value 'containerRef.current' will likely have changed by the time this effect cleanup function runs. If this ref points to a node rendered by React, copy 'containerRef.current' to a variable inside the effect, and use that variable in the cleanup function react-hooks/exhaustive-deps
Can someone please provide a more in-depth explanation as to what exactly this means or point me to a resource? As well as the solution to satisfy the error requirement. From what I can see containerRef.current
IS referenced inside the useEffect
cleanup, clearly I do not have a solid understanding of what is actually happening here.
CodePudding user response:
The warning exists because, in some cases, the .current
value referenced in the body of an effect will be different from the .current
value referenced in the cleanup function. In general, if you do
useEffect(() => {
// code that references someRef.current
return () => {
// more code that references someRef.current
};
you may well be counting on both such references to reference the same value - but that's not guaranteed, and will sometimes be a source of bugs.
In your code, there is only one line in the code which throws the error, which is this one:
return () => {
if (containerRef && containerRef.current) {
currentEl = containerRef.current; // <--------
observer.unobserve(currentEl);
}
}
Which is reasonable - there's no absolute guarantee that your
currentEl = containerRef.current;
observer.observe(currentEl);
in the effect body will be the same element unobserved in the cleanup function.
The fix would be to extract the .current
value into a variable in the effect body, and reference that variable in the cleanup.
Also note that a ref will always be truthy - no need to test it.
useEffect(() => {
const currentEl = containerRef.current;
if (!currentEl) return; // no need to attach observer or cleanup
const observer = new IntersectionObserver(callback, options);
observer.observe(currentEl);
return () => {
observer.unobserve(currentEl);
};
}, [containerRef, options])