From 20e3e890ce75d4217e4f934ea8ffe39b22c14f44 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Tue, 14 May 2024 18:09:44 +0200 Subject: [PATCH 1/4] Memoize cloned element --- src/components/Tooltip/Tooltip.tsx | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index 80c999e3..d72cacc2 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -27,6 +27,7 @@ import React, { JSX, isValidElement, cloneElement, + useMemo, } from "react"; import classNames from "classnames"; @@ -163,15 +164,21 @@ function TooltipAnchor({ children }: Readonly): JSX.Element { const childrenRef = (children as unknown as { ref?: Ref })?.ref; const ref = useMergeRefs([context.refs.setReference, childrenRef]); - if (!isValidElement(children)) { + const element = useMemo(() => { + if (!isValidElement(children)) return; + + const props = + isValidElement(children) && + context.getReferenceProps({ + ref, + ...children.props, + }); + return cloneElement(children, props); + }, [ref, children, isValidElement(children) && children.props]); + + if (!element) { throw new Error("Tooltip anchor must be a single valid React element"); } - return cloneElement( - children, - context.getReferenceProps({ - ref, - ...children.props, - }), - ); + return element; } From 30d0564448db2f361dea0920b8efe947dbc7280f Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 15 May 2024 09:44:52 +0200 Subject: [PATCH 2/4] Add comment --- src/components/Tooltip/Tooltip.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index d72cacc2..0ec7f0ff 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -174,6 +174,7 @@ function TooltipAnchor({ children }: Readonly): JSX.Element { ...children.props, }); return cloneElement(children, props); + // We need to check `isValidElement` to infer the type of `children` }, [ref, children, isValidElement(children) && children.props]); if (!element) { From 63e1f1f2465f93e788f78818b39a2a7321718b84 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 15 May 2024 10:29:52 +0200 Subject: [PATCH 3/4] Use dedicated variable for children props --- src/components/Tooltip/Tooltip.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index 0ec7f0ff..0b16710d 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -164,6 +164,9 @@ function TooltipAnchor({ children }: Readonly): JSX.Element { const childrenRef = (children as unknown as { ref?: Ref })?.ref; const ref = useMergeRefs([context.refs.setReference, childrenRef]); + // We need to check `isValidElement` to infer the type of `children` + const childrenProps = isValidElement(children) && children.props; + const element = useMemo(() => { if (!isValidElement(children)) return; @@ -171,11 +174,10 @@ function TooltipAnchor({ children }: Readonly): JSX.Element { isValidElement(children) && context.getReferenceProps({ ref, - ...children.props, + ...childrenProps, }); return cloneElement(children, props); - // We need to check `isValidElement` to infer the type of `children` - }, [ref, children, isValidElement(children) && children.props]); + }, [ref, children, childrenProps]); if (!element) { throw new Error("Tooltip anchor must be a single valid React element"); From 05e7e3dcf6b34e263fcb5e53914aa3bd91e6228c Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 15 May 2024 10:34:12 +0200 Subject: [PATCH 4/4] Remove unreachable condition --- src/components/Tooltip/Tooltip.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index 0b16710d..e0b53517 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -170,12 +170,10 @@ function TooltipAnchor({ children }: Readonly): JSX.Element { const element = useMemo(() => { if (!isValidElement(children)) return; - const props = - isValidElement(children) && - context.getReferenceProps({ - ref, - ...childrenProps, - }); + const props = context.getReferenceProps({ + ref, + ...childrenProps, + }); return cloneElement(children, props); }, [ref, children, childrenProps]);