Skip to content

Instantly share code, notes, and snippets.

@hrdtbs
Last active February 13, 2022 23:28
Show Gist options
  • Save hrdtbs/476f022a07ff2a4550f3ddbfdc0c7e3a to your computer and use it in GitHub Desktop.
Save hrdtbs/476f022a07ff2a4550f3ddbfdc0c7e3a to your computer and use it in GitHub Desktop.
React hooks of Observers
import { useLayoutEffect, useState } from "react"
let animationFrameID = 0
export const useIntersectionObserver = (
ref: React.RefObject<HTMLElement>,
options?: IntersectionObserverInit
): IntersectionObserverEntry | undefined => {
const [entry, setEntry] = useState<IntersectionObserverEntry>()
useLayoutEffect(() => {
const element = ref.current
const intersectionObserver = new IntersectionObserver(entries => {
if (!Array.isArray(entries)) {
return
}
if (!entries.length) {
return
}
animationFrameID = window.requestAnimationFrame(() => {
if (intersectionObserver) {
setEntry(entries[0])
}
})
}, options)
if (element) {
intersectionObserver.observe(element)
}
return () => {
if (element) {
intersectionObserver.unobserve(element)
}
window.cancelAnimationFrame(animationFrameID)
}
}, [options, ref])
return entry
}
import { useLayoutEffect, useState } from "react"
const defaultConfig = {
childList: true
}
let animationFrameID = 0
export const useMutationObserver = (
ref: React.RefObject<HTMLElement>,
config: MutationObserverInit = defaultConfig
): MutationRecord | undefined => {
const [entry, setEntry] = useState<MutationRecord>()
useLayoutEffect(() => {
const element = ref.current
const mutationObserver = new MutationObserver(entries => {
if (!Array.isArray(entries)) {
return
}
if (!entries.length) {
return
}
animationFrameID = window.requestAnimationFrame(() => {
if (mutationObserver) {
setEntry(entries[0])
}
})
})
if (element) {
mutationObserver.observe(element, config)
}
return () => {
if (element) {
mutationObserver.disconnect()
}
window.cancelAnimationFrame(animationFrameID)
}
}, [config, ref])
return entry
}
import { useEffect, useState } from "react"
import ResizeObserver from "resize-observer-polyfill"
let animationFrameID = 0
export const useResizeObserver = <T extends HTMLElement>(ref: React.RefObject<T>): ResizeObserverEntry | undefined => {
const [entry, setEntry] = useState<ResizeObserverEntry>()
useEffect(() => {
const element = ref.current
const resizeObserver = new ResizeObserver(entries => {
if (!Array.isArray(entries)) {
return
}
if (!entries.length) {
return
}
animationFrameID = window.requestAnimationFrame(() => {
if (resizeObserver) {
setEntry(entries[0])
}
})
})
if (element) {
resizeObserver.observe(element)
}
return () => {
if (element) {
resizeObserver.unobserve(element)
}
window.cancelAnimationFrame(animationFrameID)
}
}, [ref])
return entry
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment