primitives icon indicating copy to clipboard operation
primitives copied to clipboard

`Tooltip`: `TooltipContent` children content is being mounted to the DOM twice

Open hallucinogenizer opened this issue 1 year ago • 11 comments

Bug report

Current Behavior

Here's a codesandbox I've prepared for this bug report.

Open the console in the sandbox and reload the preview. Once the page has loaded, clear the console using console.clear(). Now hover over the tooltip trigger button.

You'll see the following logs:

Console was cleared
Render count: 1 
test: 1 

Render count: 1 
test: 2 

Render count: 2 
test: 3 

Render count: 2 
test: 4 
​

Notice how console.count('test') gets called twice even though the render count is still 1. A useEffect does not get called twice in the same render. This means there are two instances of the TooltipContent children in the DOM. Note that we're not using react strict mode.

If you set <Tooltip open={true}> allowing you to inspect the DOM, you'll even see the content mounted twice: image

There's a second mount with parent having width:1px, height:1px that is invisible.

Expected behavior

Content should be mounted once to the DOM.

The problem with mounting it twice is that by mounting twice, some useEffect() hooks that developers may be expecting would only get called once on mount would get called twice. For example, analytics calls, fetch requests, mutations.

Reproducible example

CodeSandbox

Suggested solution

Additional context

Your environment

Software Name(s) Version
Radix Package(s) react-tooltip 1.1.2
React n/a 18.0.0
Browser Chrome 126.0.6478.185 arm64
Assistive tech
Node n/a
npm/yarn
Operating System MacOS

hallucinogenizer avatar Jul 26 '24 13:07 hallucinogenizer

+1

finallyblueskies avatar Oct 01 '24 04:10 finallyblueskies

Having the same issue 👍🏼

amelie-schlueter avatar Oct 04 '24 11:10 amelie-schlueter

I'm using @radix-ui/react-tooltip as the basis for my tooltips and when I was writing some tests for it using @testing-library/react I noticed the same behavior. When searching for the text I defined as the content of the tooltip using the findByText function, my test failed because multiple instances of the same text were found. This way, when inspecting the tooltip component you can confirm that there is a duplication of the TooltipContent children. This forces me to write a wrong test or leave the component untested

ivensgustavo avatar Oct 04 '24 21:10 ivensgustavo

Having the same issue. Version: "@radix-ui/react-tooltip": "1.1.3",

Screenshot 2024-10-28 163900

YasielCabrera avatar Oct 28 '24 20:10 YasielCabrera

Any updates on this? It makes testing rather hard

gnesher avatar Nov 14 '24 12:11 gnesher

I'm having the same issue. I thought it was our implementation, but seeing this thread makes me think otherwise. Funny enough we don't get this in our app, only when testing with jest and @testing-library/react.

PaulMorel avatar Nov 28 '24 01:11 PaulMorel

Same issue, I'm forced to use getAllByText on my tests which just feels wrong and unreliable...

  • @radix-ui/react-tooltip v1.1.7
  • @testing-library/react v15.0.7
  • @testing-library/jest-dom v6.4.6

arctouch-leticiavigna avatar Feb 03 '25 16:02 arctouch-leticiavigna

Well, the tests of Tooltip primitive itself use queryAllByText

https://github.com/radix-ui/primitives/blob/6e75e117977c9e6ffa939e6951a707f16ba0f95e/packages/react/tooltip/src/tooltip.test.tsx#L45

I'm curious why there is a visually hidden primitive, probably for screen readers?

brunolopesr avatar Mar 24 '25 20:03 brunolopesr

I just encountered the same thing. After inspecting the DOM I noticed that the visually hidden tooltip content is in an element with role="tooltip" while the visual content is not, so I was able to get around the testing weirdness by using getByRole. For example:

expect(screen.getByRole('tooltip', { name: 'expected tooltip text' })).toBeInTheDocument()

wosephjeber avatar Apr 07 '25 22:04 wosephjeber

Bump

KutynaMateusz avatar Apr 14 '25 12:04 KutynaMateusz

We are having the same issue. Any work around for testing? I am using unordered list with multiple list items. And trying to verify number of list items are as expected. I could use getAllByTestId for now but that muddies the code.

sunilshahi avatar May 15 '25 04:05 sunilshahi