Skip to content

Commit 0b894a4

Browse files
fix: move document observer to separate effect
1 parent eb9e08c commit 0b894a4

File tree

1 file changed

+49
-56
lines changed

1 file changed

+49
-56
lines changed

src/components/Tooltip/Tooltip.tsx

Lines changed: 49 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -58,23 +58,6 @@ const Tooltip = ({
5858
const [anchorsBySelect, setAnchorsBySelect] = useState<HTMLElement[]>([])
5959
const mounted = useRef(false)
6060

61-
useEffect(() => {
62-
let selector = anchorSelect
63-
if (!selector && id) {
64-
selector = `[data-tooltip-id='${id}']`
65-
}
66-
if (!selector) {
67-
return
68-
}
69-
try {
70-
const anchors = Array.from(document.querySelectorAll<HTMLElement>(selector))
71-
setAnchorsBySelect(anchors)
72-
} catch {
73-
// warning was already issued in the controller
74-
setAnchorsBySelect([])
75-
}
76-
}, [anchorSelect, activeAnchor])
77-
7861
/**
7962
* useLayoutEffect runs before useEffect,
8063
* but should be used carefully because of caveats
@@ -347,11 +330,35 @@ const Tooltip = ({
347330
})
348331
})
349332

350-
const parentObserverCallback: MutationCallback = (mutationList) => {
351-
let selector = anchorSelect ?? ''
352-
if (!selector && id) {
353-
selector = `[data-tooltip-id='${id}']`
333+
return () => {
334+
if (events.find((event: string) => event === 'click')) {
335+
window.removeEventListener('click', handleClickOutsideAnchors)
336+
}
337+
if (closeOnEsc) {
338+
window.removeEventListener('keydown', handleEsc)
339+
}
340+
if (clickable) {
341+
tooltipRef.current?.removeEventListener('mouseenter', handleMouseEnterTooltip)
342+
tooltipRef.current?.removeEventListener('mouseleave', handleMouseLeaveTooltip)
354343
}
344+
enabledEvents.forEach(({ event, listener }) => {
345+
elementRefs.forEach((ref) => {
346+
ref.current?.removeEventListener(event, listener)
347+
})
348+
})
349+
}
350+
/**
351+
* rendered is also a dependency to ensure anchor observers are re-registered
352+
* since `tooltipRef` becomes stale after removing/adding the tooltip to the DOM
353+
*/
354+
}, [rendered, anchorRefs, anchorsBySelect, closeOnEsc, events])
355+
356+
useEffect(() => {
357+
let selector = anchorSelect ?? ''
358+
if (!selector && id) {
359+
selector = `[data-tooltip-id='${id}']`
360+
}
361+
const documentObserverCallback: MutationCallback = (mutationList) => {
355362
mutationList.forEach((mutation) => {
356363
if (mutation.type !== 'childList') {
357364
return
@@ -389,44 +396,13 @@ const Tooltip = ({
389396
}
390397
})
391398
}
392-
393-
const parentObserver = new MutationObserver(parentObserverCallback)
394-
399+
const documentObserver = new MutationObserver(documentObserverCallback)
395400
// watch for anchor being removed from the DOM
396-
parentObserver.observe(document.body, { attributes: false, childList: true, subtree: true })
397-
401+
documentObserver.observe(document.body, { attributes: false, childList: true, subtree: true })
398402
return () => {
399-
if (events.find((event: string) => event === 'click')) {
400-
window.removeEventListener('click', handleClickOutsideAnchors)
401-
}
402-
if (closeOnEsc) {
403-
window.removeEventListener('keydown', handleEsc)
404-
}
405-
if (clickable) {
406-
tooltipRef.current?.removeEventListener('mouseenter', handleMouseEnterTooltip)
407-
tooltipRef.current?.removeEventListener('mouseleave', handleMouseLeaveTooltip)
408-
}
409-
enabledEvents.forEach(({ event, listener }) => {
410-
elementRefs.forEach((ref) => {
411-
ref.current?.removeEventListener(event, listener)
412-
})
413-
})
414-
parentObserver.disconnect()
403+
documentObserver.disconnect()
415404
}
416-
/**
417-
* rendered is also a dependency to ensure anchor observers are re-registered
418-
* since `tooltipRef` becomes stale after removing/adding the tooltip to the DOM
419-
*/
420-
}, [
421-
rendered,
422-
anchorRefs,
423-
activeAnchor,
424-
anchorsBySelect,
425-
closeOnEsc,
426-
events,
427-
delayHide,
428-
delayShow,
429-
])
405+
}, [id, anchorSelect, activeAnchor])
430406

431407
useEffect(() => {
432408
if (position) {
@@ -496,6 +472,23 @@ const Tooltip = ({
496472
}
497473
}, [])
498474

475+
useEffect(() => {
476+
let selector = anchorSelect
477+
if (!selector && id) {
478+
selector = `[data-tooltip-id='${id}']`
479+
}
480+
if (!selector) {
481+
return
482+
}
483+
try {
484+
const anchors = Array.from(document.querySelectorAll<HTMLElement>(selector))
485+
setAnchorsBySelect(anchors)
486+
} catch {
487+
// warning was already issued in the controller
488+
setAnchorsBySelect([])
489+
}
490+
}, [id, anchorSelect])
491+
499492
const hasContentOrChildren = Boolean(html || content || children)
500493
const canShow = hasContentOrChildren && show && Object.keys(inlineStyles).length > 0
501494

0 commit comments

Comments
 (0)