useIntersectionObserver
使用 Intersection Observer API 跟蹤元素
useIntersectionObserver 封裝了 Intersection Observer API,用於觀察目標元素與祖先元素或視窗的交集變化。它回傳觀察器的 entry 和控制函式。支援設定 root、rootMargin 和 threshold 選項。
使用場景
- 實作無限捲動——當哨兵元素進入視窗時載入更多資料
- 建構基於捲動的動畫和視差效果
- 觀察多個元素的可見性以進行效能優化(如延遲渲染)
注意事項
- SSR 安全:在伺服器端渲染時為空操作。伺服器上不會建立
IntersectionObserver。 - 效能:比捲動事件監聽更高效,因為觀察器使用瀏覽器的非同步交集偵測。
- 相關 hooks:另請參閱
useElementVisibility用於簡單的可見性布林值,以及useInfiniteScroll用於自動載入更多功能。
Usage
Live Editor
function Demo() { const Spacer = () => ( <div style={{ width: "200px", height: "300px", }} /> ); const options = { root: null, rootMargin: "0px", threshold: 1, }; const intersectionRef = useRef(null); const [entry, setEntry] = useState<IntersectionObserverEntry[]>([]); const stop = useIntersectionObserver( intersectionRef, (entry) => { setEntry(entry); }, options ); return ( <div style={{ width: "400px", height: "400px", overflow: "scroll", }} > Scroll me <Spacer /> <button onClick={() => { stop(); }} > stop observe </button> <div ref={intersectionRef} style={{ width: "100px", height: "100px", padding: "20px", background: "var(--c-hj-b)", }} > {entry[0] && entry[0].intersectionRatio < 1 ? "Obscured" : "Fully in view"} </div> <Spacer /> </div> ); }
Result
API
useIntersectionObserver
Returns
() => void: 停止監聽函數
Arguments
| 參數名 | 描述 | 類型 | 預設值 |
|---|---|---|---|
| target | dom元素 | BasicTarget<Element> (必填) | - |
| callback | 回调 | IntersectionObserverCallback (必填) | - |
| options | 传递给 IntersectionObserver 的参数 | IntersectionObserverInit | undefined | - |
BasicTarget
export type BasicTarget<T extends TargetType = Element> = (() => TargetValue<T>) | TargetValue<T> | MutableRefObject<TargetValue<T>>;
TargetValue
type TargetValue<T> = T | undefined | null;
TargetType
type TargetType = HTMLElement | Element | Window | Document | EventTarget;