Skip to content

Instantly share code, notes, and snippets.

@mlnor27
Last active May 3, 2019 16:17
Show Gist options
  • Save mlnor27/49c06fe4c035ab6b10701c9e93d1cce6 to your computer and use it in GitHub Desktop.
Save mlnor27/49c06fe4c035ab6b10701c9e93d1cce6 to your computer and use it in GitHub Desktop.
A little lazyloaded image component using IntersectionObserver API
import React, { useEffect, useRef, useState } from "react";
import { string } from "prop-types";
const usePrevious = value => {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
};
const Image = ({ src, alt, ...props }) => {
const [isVisible, setVisible] = useState(false);
const img = useRef();
const prevUrl = usePrevious(src);
const observe = (entries, observer) => {
const img = entries[0];
if (img.isIntersecting) {
setVisible(true);
observer.disconnect();
}
};
useEffect(() => {
const { current } = img;
const observer = new IntersectionObserver(observe);
observer.observe(current);
return () => observer.disconnect();
}, [src]);
if (isVisible && prevUrl === src) {
props.src = src;
} else if (isVisible && prevUrl !== src) { // receiving new src props
setVisible(false);
}
return <img ref={img} alt={alt} {...props} />;
};
Image.propTypes = {
src: string.isRequired,
alt: string.isRequired
};
export default Image;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment