[site/hooks][s]: simplified observer hook
This commit is contained in:
parent
bfb8c52953
commit
fa0775f43a
|
|
@ -5,13 +5,10 @@ export const Heading = ({ level, observer }) => (props) => {
|
|||
useEffect(() => {
|
||||
/* start observing heading's intersection with the bounding box
|
||||
* set by observer's `rootMargin` */
|
||||
if (observer) {
|
||||
observer.observe(document.getElementById(props.id));
|
||||
|
||||
return () => {
|
||||
observer.unobserve(document.getElementById(props.id));
|
||||
}
|
||||
if (!observer) {
|
||||
return
|
||||
}
|
||||
observer.observe(document.getElementById(props.id));
|
||||
});
|
||||
|
||||
return React.createElement(`h${level}`, {
|
||||
|
|
|
|||
|
|
@ -4,28 +4,35 @@ import { useState, useEffect } from 'react';
|
|||
/* Creates an Intersection Observer to keep track of headings intersecting
|
||||
* a section of the viewport defined by the rootMargin */
|
||||
const getIntersectionObserver = (callback) => {
|
||||
if (typeof window !== 'undefined') {
|
||||
return new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
callback(entry);
|
||||
});
|
||||
},
|
||||
{
|
||||
root: null,
|
||||
rootMargin: "-65px 0% -85% 0%" // 65px is a navbar height
|
||||
}
|
||||
);
|
||||
}
|
||||
return new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
callback(entry);
|
||||
});
|
||||
},
|
||||
{
|
||||
root: null,
|
||||
rootMargin: "-65px 0% -85% 0%" // 65px is a navbar height
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const useHeadingsObserver = () => {
|
||||
const [activeHeading, setActiveHeading] = useState("");
|
||||
const [observer, setObserver] = useState(getIntersectionObserver((entry) => {
|
||||
const [observer, setObserver] = useState(null);
|
||||
|
||||
/* Runs only after the first render, in order to preserve the observer
|
||||
* between component rerenderings (e.g. after activeHeading change). */
|
||||
useEffect((() => {
|
||||
const observer = getIntersectionObserver((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
setActiveHeading(entry.target.id);
|
||||
}
|
||||
}));
|
||||
});
|
||||
setObserver(observer);
|
||||
|
||||
return observer.disconnect();
|
||||
}), [])
|
||||
|
||||
/* On initial render activeHeading will be `null`, since the observer
|
||||
* has not been instantiated yet. However, we still want to highlight
|
||||
|
|
|
|||
Loading…
Reference in New Issue