-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Intersection Observer API and its application #163
Labels
Comments
Intersection Observer API ApplicationsApplication on Image Lazy loading
import { useState, useEffect, useRef } from 'react';
export default function useLoadImg() {
const [state, setState] = useState<'loading' | 'loaded' | 'error'>();
const loadFuncRef = useRef<CallableFunction>(emptyFunc);
useEffect(() => {
loadFuncRef.current = async (src: string) => {
setState('loading');
try {
await loadImg(src);
setState('loaded');
} catch (e) {
setState('error');
}
}
}, []);
return {
state,
loadImg: loadFuncRef.current
};
}
function loadImg(src: string) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
resolve(void);
};
img.onerror = () => {
reject();
}
});
};
function emptyFunc (...args:any[]) {
}
const PLACEHOLDER_IMG_URL = '';
const LazyImage = ({ src, alt, className }) => {
const imgRef = useRef(null);
const { state: imgState, loadImg } = useLoadImg();
useEffect(() => {
const viewportHeight = window.innerHeight;
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.boundingClientRect.top < 1.5 * viewportHeight) {
loadImg(src);
}
});
});
const imgElem = imgRef.current;
if (imgElem) {
observer.observe(imgElem);
}
return () => {
if (imgElem) {
observer.unobserve(imgElem);
}
};
}, [loadImg, src]);
const isVisible = imgState === 'loaded';
return (
<img
alt={alt}
ref={imgRef}
src={isVisible ? src : PLACEHOLDER_IMG_URL}
/>
);
}; |
Application on Infinite loadingUse case: Implementing "infinite scrolling" websites, where more and more content is loaded and rendered as you scroll, so that the user doesn't have to flip through pages. import React, { useEffect, useRef, useState } from 'react';
const InfiniteScrollComponent: React.FC = () => {
const observer = useRef<IntersectionObserver | null>(null);
const [page, setPage] = useState(1);
const [isLoading, setIsLoading] = useState(false);
const containerRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
// Initialize Intersection Observer when component mounts
observer.current = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
// When the observed element is in view, load more content
setIsLoading(true);
setPage(prevPage => prevPage + 1);
}
});
// Start observing the container element
if (containerRef.current) {
observer.current.observe(containerRef.current);
}
return () => {
// Clean up observer when component unmounts
if (observer.current) {
observer.current.disconnect();
}
};
}, []);
useEffect(() => {
// Simulate loading more content (you would fetch data from an API here)
if (isLoading) {
// Example fetch using window.fetch
fetch(`https://api.example.com/data?page=${page}`)
.then(response => response.json())
.then(data => {
// Handle the loaded data
console.log('Loaded data:', data);
setIsLoading(false);
})
.catch(error => {
console.error('Error fetching data:', error);
setIsLoading(false);
});
}
}, [isLoading, page]);
return (
<div>
<div>
{/* Render your content here */}
{/* ... */}
</div>
<div ref={containerRef}>
{/* This is the element that will be observed */}
</div>
</div>
);
};
export default InfiniteScrollComponent; |
Application on adding css animation to html element that just jumped in user's viewimport React, { useRef, useEffect } from 'react';
import './AnimatedComponent.css'; // Create this file for your CSS animation
const AnimatedComponent = () => {
const animatedRef = useRef(null);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
entry.target.classList.add('animate'); // Add the CSS class for animation
observer.unobserve(entry.target); // Stop observing once animation is applied
}
},
{ threshold: 0.1 } // Adjust threshold as needed
);
if (animatedRef.current) {
observer.observe(animatedRef.current);
}
return () => {
if (animatedRef.current) {
observer.unobserve(animatedRef.current);
}
};
}, []);
return <div className="animated-element" ref={animatedRef}></div>;
};
export default AnimatedComponent; |
reboottime
changed the title
Intersection Observer API
Intersection Observer API and its application
Oct 12, 2023
References
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Overview
This article talks about the application of Intersection Observer API and its compatibility consideration.
The basic API
The text was updated successfully, but these errors were encountered: