adobe / adobe/react-spectrum

[react-aria-components] Tabs' onSelectionChange prop doesn't fire correctly when using tabs as links

Open
#5,252 11 comments 0 reactions 0 assignees View on GitHub
bug documentation RAC
Dominant language
TypeScript
Stars
15.9k
Forks
1.6k
Avg merge
3d 9m
Merged PRs (30d)
59

Description

### Provide a general summary of the issue here

After doing a `Tabs` implementation where we are using each `Tab` as a link, per [the docs](https://react-spectrum.adobe.com/react-aria/Tabs.html#links), I've noticed that `onSelectionChange` doesn't fire correctly.

### 🤔 Expected Behavior?

- `onSelectionChange` should fire with the current key
- `onSelectionChange` should fire on keyboard navigation between tabs

### 😯 Current Behavior

- `onSelectionChange` is firing with the _previous_ key
- `onSelectionChange` is not firing on keyboard navigation

### 💁 Possible Solution

_No response_

### 🔦 Context

I've been adding analytics functionality to our implementation of Tabs, that should track each tab change a user makes. To make it easier for our product/analytics people to use the results in their dashboards and reports, the tracking should include the tab's text value, as opposed to it's key. To do this without using `useTabList`—because we would like to keep the rest of what `Tabs` offers for 'free'—I am having to use a sub-component that can access `TabListState`, which we can then use to create the tracking function and pass it back to `Tabs` via state.

```js
const UpdateTabTrackingFunction = ({ setTrackTabChange }) => {
const tabListState = useContext(TabListStateContext);
useEffect(() => {
setTrackTabChange(() => (key) => {
track('TabChange', tabListState?.collection?.getItem(key)?.textValue);
});
}, [tabListState?.collection]); // eslint-disable-line react-hooks/exhaustive-deps
return null;
};

const CustomTabs = (props: ComponentPropsWithoutRef) => {
const [trackTabChange, setTrackTabChange] = useState(null);

const onSelectionChange = (key) => {
props.onSelectionChange?.(key);
trackTabChange?.(key);
};

return (

<>

{props.children}


);
};
```

It's a little ugly, but does the job! I should also note that it would be really nice to have access to the full tab item in `onSelectionChange`, which would help us avoid this situation.

When testing this with our tabs that use links, I noticed the reported behaviour.

### 🖥️ Steps to Reproduce

Minimal reproduction: https://codesandbox.io/p/sandbox/react-aria-components-tabs-onselectionchange-bug-cv6wh2?file=%2Fapp%2Fpage.js%3A7%2C21

### Version

1.0.0-beta-1

### What browsers are you seeing the problem on?

Firefox, Chrome, Safari

### If other, please specify.

_No response_

### What operating system are you using?

MacOS

### 🧢 Your Company/Team

_No response_

### 🕷 Tracking Issue

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.