primitives
primitives copied to clipboard
Tabs onValueChange fires twice when there is a delay in setState
Bug report
Current Behavior
When using the Tabs component, the onValueChange prop is triggered twice if there's a delay in the setState operation, like when using a setTimeout to set the state. This behavior is unexpected and can lead to issues in state management or side effects being triggered more than once.
Expected behavior
The onValueChange prop should only fire once per user interaction, regardless of any delay in state updates or the use of asynchronous operations within the handler.
Reproducible example
Here's a CodeSandbox that demonstrates the issue: Tabs Bug Demo
In this demo, a setTimeout simulates an artificial delay in the state update within the onValueChange handler. The console logs the value change twice, illustrating the bug.
Additional context
This issue is particularly impactful in scenarios where the Tabs component's selected state is synchronized with the URL, and the source of truth for the selected tab comes from the URL parameters. This is a common pattern for ensuring that the tab state remains consistent with browser navigation (e.g., back and forward buttons) and direct URL access.
Additionally, the double invocation of onValueChange can lead to issues in a Next.js app. Specifically, it causes Next.js to cancel the ongoing page load and then load the page again. Furthermore, this behavior results in getInitialProps being called twice, leading to redundant API calls.
Your environment
| Software | Name(s) | Version |
|---|---|---|
| Radix Package(s) | tabs | 1.0.4 |
| React | n/a | 18.2 |
| Browser | Chrome | 121 |
| Assistive tech | n/a | |
| Node | n/a | 21 |
| npm/yarn | yarn | 1.22 |
| Operating System | MacOS | 14 |
This can be fixed by passing activationMode="manual". Feel free to close this issue if this is the intended behavior!
Hey @Abdallatif the sandbox is inaccessible, can you update it?