Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to cleanup useRef in useEffect?

I have this component, so I want to clean up in useEffect. I googled the issue and there is no helpful information.

const LoadableImg = ({src, alt}) => {
const [isLoaded, setIsLoaded] = useState(false);

let imageRef = useRef(null);


useEffect(() => {
    if (isLoaded) return;
    if (imageRef.current) {
        imageRef.current.onload = () => setIsLoaded(true);
    }
    return () => {
        imageRef.current = null;
    };
}, [isLoaded]);

return (
    <div className={isLoaded ? 'l_container_loaded' : 'l_container'}>
        <img ref={imageRef} className={isLoaded ? "l_image_loaded" : 'l_image'}
             src={src}
             alt={alt}/>
    </div>
) };

I can’t figure out how to clean up in useEffect.

UPDATE
added another useEffect, according to Arcanus answer.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const LoadableImg = ({src, alt}) => {
const [isLoaded, setIsLoaded] = useState(false);

let imageRef = useRef(null);


useEffect(() => {
    if (isLoaded) return;
    if (imageRef.current) {
        imageRef.current.onload = () => setIsLoaded(true);
    }

}, [isLoaded]);

useEffect(() => {
    return () => {
        imageRef.current = null;
    };
},[])


return (
    <div className={isLoaded ? 'l_container_loaded' : 'l_container'}>
        <img ref={imageRef} className={isLoaded ? "l_image_loaded" : 'l_image'}
             src={src}
             alt={alt}/>
    </div>
)};

>Solution :

If you want to do this with a ref, then you will need to remove the onload function, but you do not need to null out imageRef.current:

useEffect(() => {
    if (isLoaded) return;
    const element = imageRef.current;
    if (element) {
        element.onload = () => setIsLoaded(true);
        return () => {
            element.onload = null;
        }
    }
}, [isLoaded]);

That said, i recommend you do not use a ref for this. A standard onLoad prop will work just as well, without the need for all the extra logic for adding and removing the event listener:

const LoadableImg = ({ src, alt }) => {
  const [isLoaded, setIsLoaded] = useState(false);

  return (
    <div className={isLoaded ? "l_container_loaded" : "l_container"}>
      <img
        className={isLoaded ? "l_image_loaded" : "l_image"}
        src={src}
        alt={alt}
        onLoad={() => setIsLoaded(true)}
      />
    </div>
  );
};
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading