Reputation: 2290
I am trying to get the top
and bottom
measurements from multiple elements by using IntersectionObserver
. However, once I have the measurements, how can I unobserve
the elements.
The problem is that each element is position: sticky
and when scrolling additional values are added to the array
and I only want the measurements from the initial render.
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
const measurement = {
top: entry.boundingClientRect.top,
bottom: entry.boundingClientRect.bottom,
};
console.log(measurement);
});
});
useEffect(() => {
const sections = document.querySelectorAll(`section#dark`)
sections.forEach((section) => observer.observe(section));
return () => {
// observer.disconnect(); removed in Stackoverflow edit
sections.forEach(section => observer.observe(section)); // Added in Stackoverflow edit
};
}, []);
I have tried using observer.unobserve()
but cannot figure out what value it requires as it returns an error of Argument of type 'NodeListOf<Element>' is not assignable to parameter of type 'Element'.
EDIT: I figured out how to use oberver.unobserve
with sections.forEach(section => observer.unobserve(section));
but it still adds more records when scrolling.
Full example can be seen here StackBlitz
Upvotes: 4
Views: 2410
Reputation: 13078
You need to move the observer instance to useEffect
block because every time your component is updated a new IntersectionObserver
instance is created:
useEffect(() => {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
const measurement = {
top: entry.boundingClientRect.top,
bottom: entry.boundingClientRect.bottom,
};
console.log(measurement);
observer.unobserve(entry.target); //<-- call unobserve here
});
});
const sections = document.querySelectorAll(`section#dark`)
sections.forEach((section) => observer.observe(section));
return () => {
observer.disconnect();
};
}, []);
Upvotes: 5