1
- import { useEffect , useState , useRef } from 'react'
1
+ import { useEffect , useState , useRef , useLayoutEffect } from 'react'
2
2
import classNames from 'classnames'
3
3
import debounce from 'utils/debounce'
4
4
import { TooltipContent } from 'components/TooltipContent'
@@ -50,6 +50,19 @@ const Tooltip = ({
50
50
const { anchorRefs, setActiveAnchor : setProviderActiveAnchor } = useTooltip ( id )
51
51
const [ activeAnchor , setActiveAnchor ] = useState < React . RefObject < HTMLElement > > ( { current : null } )
52
52
const hoveringTooltip = useRef ( false )
53
+ const mounted = useRef ( false )
54
+
55
+ /**
56
+ * useLayoutEffect runs before useEffect,
57
+ * but should be used carefully because of caveats
58
+ * https://beta.reactjs.org/reference/react/useLayoutEffect#caveats
59
+ */
60
+ useLayoutEffect ( ( ) => {
61
+ mounted . current = true
62
+ return ( ) => {
63
+ mounted . current = false
64
+ }
65
+ } , [ ] )
53
66
54
67
useEffect ( ( ) => {
55
68
if ( ! show ) {
@@ -58,12 +71,20 @@ const Tooltip = ({
58
71
} , [ show ] )
59
72
60
73
const handleShow = ( value : boolean ) => {
74
+ if ( ! mounted . current ) {
75
+ return
76
+ }
77
+
61
78
setRendered ( true )
62
79
/**
63
80
* wait for the component to render and calculate position
64
81
* before actually showing
65
82
*/
66
83
setTimeout ( ( ) => {
84
+ if ( ! mounted . current ) {
85
+ return
86
+ }
87
+
67
88
setIsOpen ?.( value )
68
89
if ( isOpen === undefined ) {
69
90
setShow ( value )
@@ -345,7 +366,7 @@ const Tooltip = ({
345
366
if ( position ) {
346
367
// if `position` is set, override regular and `float` positioning
347
368
handleTooltipPosition ( position )
348
- return ( ) => null
369
+ return
349
370
}
350
371
351
372
if ( float ) {
@@ -360,15 +381,14 @@ const Tooltip = ({
360
381
handleTooltipPosition ( lastFloatPosition . current )
361
382
}
362
383
// if `float` is set, override regular positioning
363
- return ( ) => null
384
+ return
364
385
}
365
386
366
387
let elementReference = activeAnchor . current
367
388
if ( anchorId ) {
368
389
// `anchorId` element takes precedence
369
390
elementReference = document . querySelector ( `[id='${ anchorId } ']` ) as HTMLElement
370
391
}
371
- let mounted = true
372
392
computeTooltipPosition ( {
373
393
place,
374
394
offset,
@@ -378,7 +398,7 @@ const Tooltip = ({
378
398
strategy : positionStrategy ,
379
399
middlewares,
380
400
} ) . then ( ( computedStylesData ) => {
381
- if ( ! mounted ) {
401
+ if ( ! mounted . current ) {
382
402
// invalidate computed positions after remount
383
403
return
384
404
}
@@ -389,9 +409,6 @@ const Tooltip = ({
389
409
setInlineArrowStyles ( computedStylesData . tooltipArrowStyles )
390
410
}
391
411
} )
392
- return ( ) => {
393
- mounted = false
394
- }
395
412
} , [ show , anchorId , activeAnchor , content , html , place , offset , positionStrategy , position ] )
396
413
397
414
useEffect ( ( ) => {
0 commit comments