useIntersectionObserver
zyeon/use-intersection-observerFreeHook
A callback-ref hook reporting whether an element is intersecting its viewport, with an optional one-shot reveal-once mode.
See it running
Open the demo on zyeon
ui.zyeon.ai/r/use-intersection-observerInstall it
npx shadcn@latest add https://ui.zyeon.ai/r/use-intersection-observer.jsonSource
1"use client"23import * as React from "react"45export interface UseIntersectionObserverOptions {6 /** Passed through to `IntersectionObserver` as `threshold`. Default 0. */7 threshold?: number | number[]8 /** Passed through to `IntersectionObserver` as `rootMargin`. Default "0px". */9 rootMargin?: string10 /** Disconnect the observer the first time the element intersects. Default false. */11 once?: boolean12}1314export interface UseIntersectionObserverResult<T extends Element> {15 /** Callback ref — attach it to the element you want to observe. */16 ref: (node: T | null) => void17 isIntersecting: boolean18 entry: IntersectionObserverEntry | null19}2021/**22 * 用**callback ref**(不是 `useRef` + `useEffect`)订阅一个元素的可见性。这是23 * 比 `ref` 对象更稳的姿势:`ref` 对象只在挂载时读一次 `.current`,元素被条件24 * 渲染替换(换 key、换分支)时不会自动重新 observe;callback ref 由 React 在25 * 节点挂载/替换/卸载时逐次调用,天然拿到「现在到底在观察哪个节点」的真相,26 * 于是重新 observe 变成免费的。27 *28 * `ref` 回调本身用 `React.useCallback` 包裹,依赖数组是 `[observerInit, once]`,29 * 其中 `observerInit` 是把 `threshold`/`rootMargin` 序列化成字符串(`thresholdKey`30 * = `JSON.stringify(threshold)`)后再 `useMemo` 出来的 —— `threshold` 常是调用方31 * 每次渲染现写的数组字面量(`[0, 0.5]`),按引用比较会导致每次渲染都判定“变了”32 * 从而无谓地 disconnect/reconnect;以序列化值为 key 之后,内容不变时 `observerInit`33 * 保持同一个对象身份,`ref` 回调也保持同一份函数身份,已挂载的节点不会被重新34 * observe。35 *36 * 只有 `observerInit`/`once` 真的变化(调用方显式改了 threshold/rootMargin/once)37 * 时,React 才会用新的 `ref` 函数身份替换旧的——这一步 React 会自动先用 `null`38 * 调一次旧函数、再用当前节点调一次新函数,于是「断开旧 observer、按新 options39 * 重新 observe」全部发生在 callback ref 里,不需要额外的 `useEffect`。40 *41 * 生命周期:节点挂载→(SSR/无 `IntersectionObserver` 时直接跳过)建 observer→42 * observe;每次交叉状态变化在 observer 的(异步)回调里 `setState`,不是在渲染期43 * 或 effect 体内同步 `setState`;`once` 为 true 时,一旦交叉就 `disconnect()`44 * 并保留 `isIntersecting: true`,后续不再触发;节点被替换或组件卸载时,45// … truncated
Files it writes
More from zyeon
All 517 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| useAsyncuse-async | zyeon | Hooks | Free | no deps | |
| useBroadcastChanneluse-broadcast-channel | zyeon | Hooks | Free | no deps | |
| useClickOutsideuse-click-outside | zyeon | Hooks | Free | no deps | |
| useClipboardPasteuse-clipboard-paste | zyeon | Hooks | Free | no deps | |
| useControllableStateuse-controllable-state | zyeon | Hooks | Free | no deps | |
| useCopyToClipboarduse-copy-to-clipboard | zyeon | Hooks | Free | no deps | |
| useCountdownuse-countdown | zyeon | Hooks | Free | no deps | |
| useDebounceValueuse-debounce-value | zyeon | Hooks | Free | no deps |
