From 1e67657abff07194bfccc26b43d7734459754877 Mon Sep 17 00:00:00 2001 From: Gwendolen Lynch Date: Wed, 21 Dec 2022 16:58:46 +0100 Subject: [PATCH] fix: React 18 support for tooltip modal --- src/components/Portal.tsx | 23 +++++++++++++++++++++++ src/components/Tooltip.tsx | 20 +++++++++----------- src/hooks/usePortalElement.ts | 22 +++++++++++----------- 3 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 src/components/Portal.tsx diff --git a/src/components/Portal.tsx b/src/components/Portal.tsx new file mode 100644 index 00000000..0a515054 --- /dev/null +++ b/src/components/Portal.tsx @@ -0,0 +1,23 @@ +import React from 'react' +import ReactDOM from 'react-dom' +import usePortalElement from '../hooks/usePortalElement' + +interface PortalProps { + children?: React.ReactNode | React.ReactNode[] +} + +function Portal({ children }: PortalProps): React.ReactPortal { + const portal = usePortalElement() + const modal = document.createElement('div') + + React.useLayoutEffect(() => { + if (!portal) return + portal.appendChild(modal) + + return () => portal.removeChild(modal) as unknown as void + }, [modal, portal]) + + return ReactDOM.createPortal(children, modal) +} + +export default Portal diff --git a/src/components/Tooltip.tsx b/src/components/Tooltip.tsx index 0c60cbe9..e5ba74ab 100644 --- a/src/components/Tooltip.tsx +++ b/src/components/Tooltip.tsx @@ -1,5 +1,4 @@ import React from 'react' -import ReactDOM from 'react-dom' import { useAnchor } from '../hooks/useAnchor' import useLatestWhen from '../hooks/useLatestWhen' @@ -11,6 +10,7 @@ import useChartContext from '../utils/chartContext' import TooltipRenderer from './TooltipRenderer' import useRect from '../hooks/useRect' import { useSpring } from '../hooks/useSpring' +import Portal from './Portal'; // @@ -44,7 +44,7 @@ export function defaultTooltip( } } -export default function Tooltip(): React.ReactPortal | null { +export default function Tooltip(): JSX.Element | null { const { focusedDatumState, getOptions, @@ -63,7 +63,8 @@ export default function Tooltip(): React.ReactPortal | null { const portalEl = usePortalElement() - const [tooltipEl, setTooltipEl] = React.useState() + const tooltipRef = React.useRef(null) + const tooltipInnerRef = React.useRef(null) const svgRect = useRect(svgRef.current, !!focusedDatum?.element) @@ -103,7 +104,7 @@ export default function Tooltip(): React.ReactPortal | null { show: !!focusedDatum, portalEl, anchorEl, - tooltipEl, + tooltipEl: tooltipInnerRef.current, side: ['right', 'left', 'top', 'bottom'], }) @@ -112,8 +113,6 @@ export default function Tooltip(): React.ReactPortal | null { const { visibility, ...anchorStyle } = latestStableAnchor.style - const tooltipRef = React.useRef(null) - const immediate = Number.isNaN(previousAnchor?.style.left) const tooltipXSpring = useSpring( @@ -157,7 +156,7 @@ export default function Tooltip(): React.ReactPortal | null { const latestFit = useLatestWhen(anchor.fit, !!anchor.fit) return show && portalEl - ? ReactDOM.createPortal( + ? (
(): React.ReactPortal | null { }} >
setTooltipEl(el)} + ref={() => tooltipInnerRef} style={{ fontFamily: 'sans-serif', ...(latestFit?.startKey === 'left' @@ -190,8 +189,7 @@ export default function Tooltip(): React.ReactPortal | null { anchor, })}
-
, - portalEl - ) + +
) : null } diff --git a/src/hooks/usePortalElement.ts b/src/hooks/usePortalElement.ts index 0f2b8808..48f057b2 100644 --- a/src/hooks/usePortalElement.ts +++ b/src/hooks/usePortalElement.ts @@ -16,22 +16,22 @@ export default function usePortalElement() { element.setAttribute('id', 'react-charts-portal') - Object.assign(element.style, { - pointerEvents: 'none', - position: 'fixed', - left: 0, - right: 0, - top: 0, - bottom: 0, - 'z-index': 99999999999, - }) - document.body.append(element) } + Object.assign(element.style, { + pointerEvents: 'none', + position: 'fixed', + left: 0, + right: 0, + top: 0, + bottom: 0, + 'z-index': 99999999999, + }) + setPortalEl(element) } - }) + }, []) return portalEl }