diff --git a/common/changes/@visactor/vchart/fix-tooltip-customized-render_2025-05-27-07-51.json b/common/changes/@visactor/vchart/fix-tooltip-customized-render_2025-05-27-07-51.json new file mode 100644 index 0000000000..daaa30af47 --- /dev/null +++ b/common/changes/@visactor/vchart/fix-tooltip-customized-render_2025-05-27-07-51.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: customized render of tooltip should be render in react 17 and react 18\n\n", + "type": "none", + "packageName": "@visactor/vchart" + } + ], + "packageName": "@visactor/vchart", + "email": "dingling112@gmail.com" +} \ No newline at end of file diff --git a/packages/react-vchart/src/charts/BaseChart.tsx b/packages/react-vchart/src/charts/BaseChart.tsx index 377ab6986e..d9b0840317 100644 --- a/packages/react-vchart/src/charts/BaseChart.tsx +++ b/packages/react-vchart/src/charts/BaseChart.tsx @@ -149,6 +149,7 @@ const BaseChart: React.FC = React.forwardRef((props, ref) => { const specFromChildren = useRef>(null); const eventsBinded = React.useRef(null); const skipFunctionDiff = !!props.skipFunctionDiff; + const [tooltipNode, setTooltipNode] = useState(null); const parseSpec = (props: Props) => { let spec: ISpec; @@ -169,7 +170,7 @@ const BaseChart: React.FC = React.forwardRef((props, ref) => { } as ISpec; } - const tooltipSpec = initCustomTooltip(props, spec.tooltip); + const tooltipSpec = initCustomTooltip(setTooltipNode, props, spec.tooltip); if (tooltipSpec) { spec.tooltip = tooltipSpec; } @@ -294,6 +295,7 @@ const BaseChart: React.FC = React.forwardRef((props, ref) => { ); })} + {tooltipNode} ); diff --git a/packages/react-vchart/src/components/tooltip/util.tsx b/packages/react-vchart/src/components/tooltip/util.tsx index 5c8cbcf672..882ea65432 100644 --- a/packages/react-vchart/src/components/tooltip/util.tsx +++ b/packages/react-vchart/src/components/tooltip/util.tsx @@ -1,13 +1,17 @@ +// eslint-disable-next-line @typescript-eslint/consistent-type-imports import React from 'react'; import type { BaseChartProps } from '../../charts/BaseChart'; import type { TooltipProps, TooltipRender } from './interface'; import type { ITooltipSpec } from '@visactor/vchart'; import { REACT_TOOLTIP_ClASS_NAME } from './constant'; -import { createRoot } from 'react-dom/client'; -import { render as reactRender } from 'react-dom'; +import { createPortal } from 'react-dom'; /** tooltip 自定义插槽 */ -export const initCustomTooltip = (props: BaseChartProps, spec?: TooltipProps) => { +export const initCustomTooltip = ( + setTooltipNode: React.Dispatch>, + props: BaseChartProps, + spec?: TooltipProps +) => { let render: TooltipRender; if (spec?.tooltipRender) { render = spec.tooltipRender; @@ -44,28 +48,9 @@ export const initCustomTooltip = (props: BaseChartProps, spec?: TooltipProps) => } } - let container = el.querySelector(`.${REACT_TOOLTIP_ClASS_NAME}`); - if (!container) { - // eslint-disable-next-line no-undef - container = document.createElement('div'); - container.className = REACT_TOOLTIP_ClASS_NAME; - el.appendChild(container); - } - const element = render(el, actualTooltip, params); - const finalElement = React.isValidElement(element) ? element : {element}; - - if (createRoot) { - if ((container as any).reactRoot) { - (container as any).reactRoot.render(finalElement); - } else { - const root = createRoot(container); - (container as any).reactRoot = root; - root.render(finalElement); - } - } else { - // react 17 以及以下 - reactRender(finalElement, container); - } + setTooltipNode( + createPortal(
{render(el, actualTooltip, params)}
, el) + ); } } as ITooltipSpec; } diff --git a/packages/react-vchart/src/containers/withContainer.tsx b/packages/react-vchart/src/containers/withContainer.tsx index a6bc8dd5fe..ad5a79e7e0 100644 --- a/packages/react-vchart/src/containers/withContainer.tsx +++ b/packages/react-vchart/src/containers/withContainer.tsx @@ -5,6 +5,7 @@ export interface ContainerProps { className?: string; width?: number | string; height?: number | string; + id?: string; } export default function withContainer( @@ -15,7 +16,7 @@ export default function withContainer( const Cls = React.forwardRef((props: CompProps & Props, ref) => { const container = useRef(); const [inited, setInited] = useState(false); - const { className, style, width, ...options } = props; + const { className, style, width, height, id, ...options } = props; useLayoutEffect(() => { setInited(true); @@ -24,11 +25,12 @@ export default function withContainer( return (