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'
@@ -73,6 +73,19 @@ const Tooltip = ({
73
73
setAnchorsBySelect ( [ ] )
74
74
}
75
75
} , [ anchorSelect ] )
76
+ const mounted = useRef ( false )
77
+
78
+ /**
79
+ * useLayoutEffect runs before useEffect,
80
+ * but should be used carefully because of caveats
81
+ * https://beta.reactjs.org/reference/react/useLayoutEffect#caveats
82
+ */
83
+ useLayoutEffect ( ( ) => {
84
+ mounted . current = true
85
+ return ( ) => {
86
+ mounted . current = false
87
+ }
88
+ } , [ ] )
76
89
77
90
useEffect ( ( ) => {
78
91
if ( ! show ) {
@@ -91,12 +104,18 @@ const Tooltip = ({
91
104
} , [ show ] )
92
105
93
106
const handleShow = ( value : boolean ) => {
107
+ if ( ! mounted . current ) {
108
+ return
109
+ }
94
110
setRendered ( true )
95
111
/**
96
112
* wait for the component to render and calculate position
97
113
* before actually showing
98
114
*/
99
115
setTimeout ( ( ) => {
116
+ if ( ! mounted . current ) {
117
+ return
118
+ }
100
119
setIsOpen ?.( value )
101
120
if ( isOpen === undefined ) {
102
121
setShow ( value )
@@ -375,23 +394,13 @@ const Tooltip = ({
375
394
* rendered is also a dependency to ensure anchor observers are re-registered
376
395
* since `tooltipRef` becomes stale after removing/adding the tooltip to the DOM
377
396
*/
378
- } , [
379
- rendered ,
380
- anchorRefs ,
381
- activeAnchor ,
382
- closeOnEsc ,
383
- anchorId ,
384
- anchorsBySelect ,
385
- events ,
386
- delayHide ,
387
- delayShow ,
388
- ] )
397
+ } , [ rendered , anchorRefs , activeAnchor , closeOnEsc , events , delayHide , delayShow ] )
389
398
390
399
useEffect ( ( ) => {
391
400
if ( position ) {
392
401
// if `position` is set, override regular and `float` positioning
393
402
handleTooltipPosition ( position )
394
- return ( ) => null
403
+ return
395
404
}
396
405
397
406
if ( float ) {
@@ -406,10 +415,9 @@ const Tooltip = ({
406
415
handleTooltipPosition ( lastFloatPosition . current )
407
416
}
408
417
// if `float` is set, override regular positioning
409
- return ( ) => null
418
+ return
410
419
}
411
420
412
- let mounted = true
413
421
computeTooltipPosition ( {
414
422
place,
415
423
offset,
@@ -419,7 +427,7 @@ const Tooltip = ({
419
427
strategy : positionStrategy ,
420
428
middlewares,
421
429
} ) . then ( ( computedStylesData ) => {
422
- if ( ! mounted ) {
430
+ if ( ! mounted . current ) {
423
431
// invalidate computed positions after remount
424
432
return
425
433
}
@@ -430,21 +438,7 @@ const Tooltip = ({
430
438
setInlineArrowStyles ( computedStylesData . tooltipArrowStyles )
431
439
}
432
440
} )
433
- return ( ) => {
434
- mounted = false
435
- }
436
- } , [
437
- show ,
438
- anchorId ,
439
- anchorsBySelect ,
440
- activeAnchor ,
441
- content ,
442
- html ,
443
- place ,
444
- offset ,
445
- positionStrategy ,
446
- position ,
447
- ] )
441
+ } , [ show , activeAnchor , content , html , place , offset , positionStrategy , position ] )
448
442
449
443
useEffect ( ( ) => {
450
444
const anchorById = document . querySelector < HTMLElement > ( `[id='${ anchorId } ']` )
0 commit comments