Skip to content

Commit

Permalink
fix(react-utils): useOnElementResize always invokes callback in setTi…
Browse files Browse the repository at this point in the history
…meout to avoid resize observer error
  • Loading branch information
matej21 committed Oct 31, 2023
1 parent 2e52f1f commit ff35d84
Showing 1 changed file with 30 additions and 33 deletions.
63 changes: 30 additions & 33 deletions packages/react-utils/src/hooks/useOnElementResize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,37 @@ export function useOnElementResize(

useLayoutEffect(() => {
const element = unwrapRefValue(refOrElement)
if (!element) {
return
}
if (!(element instanceof HTMLElement)) {
throw new Error('Exhaustive error: Expecting element to be instance of HTMLElement')
}

let timeoutID: number | undefined = undefined

function debouncedOnChange([entry]: ResizeObserverEntry[]) {
const timeStamp = Date.now()
const delta = timeStamp - lastTimeStamp.current

clearTimeout(timeoutID)
const timeoutFinal = delta > timeout ? 0 : timeout

timeoutID = setTimeout(() => {
const message = timeoutFinal > 0 ? 'element.resize:debounced' : 'element.resize:immediate'
scopedConsoleRef.current.warned(message, null)
callbackRef.current(entry)
lastTimeStamp.current = timeStamp
}, timeoutFinal)
}

const resizeObserver = new ResizeObserver(debouncedOnChange)

resizeObserver.observe(element, { box })

if (element) {
if (element instanceof HTMLElement) {
let timeoutID: number | undefined = undefined

function debouncedOnChange([entry]: ResizeObserverEntry[]) {
const timeStamp = Date.now()
const delta = timeStamp - lastTimeStamp.current

if (delta > timeout) {
scopedConsoleRef.current.warned('element.resize:immediate', null)
callbackRef.current(entry)
lastTimeStamp.current = timeStamp
} else {
clearTimeout(timeoutID)
timeoutID = setTimeout(() => {
scopedConsoleRef.current.warned('element.resize:debounced', null)
callbackRef.current(entry)
lastTimeStamp.current = timeStamp
}, timeout)
}
}

const resizeObserver = new ResizeObserver(debouncedOnChange)

resizeObserver.observe(element, { box })

return () => {
clearTimeout(timeoutID)
resizeObserver.unobserve(element)
}
} else {
throw new Error('Exhaustive error: Expecting element to be instance of HTMLElement')
}
return () => {
clearTimeout(timeoutID)
resizeObserver.unobserve(element)
}
}, [box, refOrElement, scopedConsoleRef, timeout])
}

0 comments on commit ff35d84

Please sign in to comment.