`Tooltip`: `TooltipContent` children content is being mounted to the DOM twice
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:
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
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 |
+1
Having the same issue 👍🏼
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
Having the same issue.
Version: "@radix-ui/react-tooltip": "1.1.3",
Any updates on this? It makes testing rather hard
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.
Same issue, I'm forced to use getAllByText on my tests which just feels wrong and unreliable...
-
@radix-ui/react-tooltipv1.1.7 -
@testing-library/reactv15.0.7 -
@testing-library/jest-domv6.4.6
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?
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()
Bump
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.