Skip to content

Commit

Permalink
fix(Tooltip): ensure timers cleanup on unmount (#1642)
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker authored Oct 17, 2022
1 parent 23de874 commit 6dd4b7b
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ export default function TooltipContainer(
return width + height
}

const clearTimers = () => {
clearTimeout(debounceTimeout.current)
}

React.useLayoutEffect(() => {
const addPositionObserver = () => {
if (resizeObserver.current || typeof document === 'undefined') {
Expand All @@ -67,7 +71,7 @@ export default function TooltipContainer(

try {
resizeObserver.current = new ResizeObserver(() => {
clearTimeout(debounceTimeout.current)
clearTimers()
debounceTimeout.current = setTimeout(
() => forceRerender(getBodySize()),
100
Expand All @@ -80,7 +84,7 @@ export default function TooltipContainer(
}
}
const removePositionObserver = () => {
clearTimeout(debounceTimeout.current)
clearTimers()
resizeObserver.current?.disconnect()
}

Expand Down
10 changes: 8 additions & 2 deletions packages/dnb-eufemia/src/components/tooltip/TooltipPortal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ function TooltipPortal(props: TooltipProps & TooltipPortalProps) {
}
}

const clearTimers = () => {
clearTimeout(tooltipPortal[id]?.delayTimeout)
clearTimeout(tooltipPortal[id]?.hiddenTimeout)
}

const removeFromDOM = (hide?: boolean) => {
if (isActive && hide) {
return // stop here
Expand Down Expand Up @@ -85,8 +90,7 @@ function TooltipPortal(props: TooltipProps & TooltipPortalProps) {
React.useEffect(() => {
setIsMounted(true)

clearTimeout(tooltipPortal[id]?.delayTimeout)
clearTimeout(tooltipPortal[id]?.hiddenTimeout)
clearTimers()

if (active) {
makePortal()
Expand Down Expand Up @@ -128,6 +132,8 @@ function TooltipPortal(props: TooltipProps & TooltipPortalProps) {
}
}

return clearTimers

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [children, active, id, hideDelay, noAnimation])

Expand Down
24 changes: 9 additions & 15 deletions packages/dnb-eufemia/src/components/tooltip/TooltipWithEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@ function TooltipWithEvents(props: TooltipProps & TooltipWithEventsProps) {
React.useState(false)
const [isMounted, setIsMounted] = React.useState(!target)

const onEnterTimeout = React.useRef<NodeJS.Timeout>()
const onLeaveTimeout = React.useRef<NodeJS.Timeout>()
const delayTimeout = React.useRef<NodeJS.Timeout>()
const cloneRef = React.useRef<HTMLElement>()
const targetRef = React.useRef<HTMLElement>()

const clearTimers = () => {
clearTimeout(delayTimeout.current)
}

React.useLayoutEffect(() => {
targetRef.current = getRefElement(cloneRef)
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand All @@ -57,9 +60,7 @@ function TooltipWithEvents(props: TooltipProps & TooltipWithEventsProps) {

return () => {
clearTimers()
if (targetRef.current) {
removeEvents(targetRef.current)
}
removeEvents(targetRef.current)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
Expand Down Expand Up @@ -103,6 +104,7 @@ function TooltipWithEvents(props: TooltipProps & TooltipWithEventsProps) {
}

const removeEvents = (element: HTMLElement) => {
if (!element) return
try {
element.removeEventListener('click', onMouseLeave)
element.removeEventListener('focus', onFocus)
Expand All @@ -116,11 +118,6 @@ function TooltipWithEvents(props: TooltipProps & TooltipWithEventsProps) {
}
}

const clearTimers = () => {
clearTimeout(onEnterTimeout.current)
clearTimeout(onLeaveTimeout.current)
}

const onFocus = (e: MouseEvent) => {
/**
* VoiceOver needs to show the Tooltip in order to read the aria-describedby
Expand All @@ -146,7 +143,7 @@ function TooltipWithEvents(props: TooltipProps & TooltipWithEventsProps) {
run()
} else {
clearTimers()
onEnterTimeout.current = setTimeout(
delayTimeout.current = setTimeout(
run,
parseFloat(String(showDelay)) || 1
) // have min 1 to make sure we are after onMouseLeave
Expand Down Expand Up @@ -174,10 +171,7 @@ function TooltipWithEvents(props: TooltipProps & TooltipWithEventsProps) {
}

if (skipPortal) {
onLeaveTimeout.current = setTimeout(
run,
parseFloat(String(hideDelay))
)
delayTimeout.current = setTimeout(run, parseFloat(String(hideDelay)))
} else {
run()
}
Expand Down

0 comments on commit 6dd4b7b

Please sign in to comment.