Autocomplete + Menu with createLink(MenuItem) fires two synthetic clicks on Enter key
- 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
When using TanStack Router's createLink() to wrap MenuItem inside an Autocomplete, pressing Enter on a focused menu item triggers two synthetic click events instead of one. This causes double navigation and duplicate browser history entries.
Both click events have isTrusted: false, indicating they are both programmatically dispatched by React Aria rather than native browser events.
### 🤔 Expected Behavior?
When pressing Enter on a focused MenuItem that is wrapped with createLink() inside an Autocomplete, only one click event should be fired, resulting in a single navigation and no duplicated browser history entries.
### 😯 Current Behavior
When pressing Enter on a focused MenuItem inside AutoComplete, multiple click events are fired, resulting in duplicated browser history entries.
Two synthetic click events are fired in sequence:
1. onClick #1 - Fired on keydown (~0ms)
2. onClick #2 - Fired on keyup (~130-150ms later, immediately after onPress)
```typescript
Debug output showing the timeline:
onClick #1 {isTrusted: false, target: 'A', currentTarget: 'A', time: 3878.8}
pushState #1 {url: '/users', time: 3886.3}
onPress {pointerType: 'keyboard', time: 4029}
onClick #2 {isTrusted: false, target: 'A', currentTarget: 'A', time: 4029.5}
```
### 💁 Possible Solution
The issue appears to be a coordination problem between two keyboard handling systems:
1. Autocomplete's keyboard handler - Triggers a click on Enter keydown to select/activate the focused item
2. usePress's keyboard handler - Calls triggerSyntheticClickEvent on Enter keyup (immediately after firing onPress)
Looking at useMenuItem.ts:285-297, there's already a guard to prevent double-clicking for anchor elements:
```typescript
case 'Enter':
interaction.current = {pointerType: 'keyboard', key: 'Enter'};
// Trigger click unless this is a link. Links trigger click natively.
if ((e.target as HTMLElement).tagName !== 'A') {
(e.target as HTMLElement).click();
}
break;
```
However, onClick #1 seems to originate from Autocomplete's item selection logic rather than useMenuItem's keyboard handler.
Possible fixes:
1. Coordinate Autocomplete and usePress to prevent both from firing clicks
2. Add deduplication logic to prevent rapid successive synthetic clicks on the same element
3. Check if a navigation is already in progress before triggering another click
### 🔦 Context
I am building a command palette/menu (similar to VS Code's Cmd+K) using:
- Autocomplete for search/filtering
- Menu + MenuItem for the list items
- TanStack Router's createLink(MenuItem) for navigation
This is a production application where the double navigation causes:
- Duplicate entries in browser history
- Confusing back-button behavior for users
- Inconsistent navigation state
Current workaround: I block the second click by setting a flag in onPress and checking it in onClick:
```typescript
const blockNextClickRef = useRef(false);
const handleClick = useCallback((e: React.MouseEvent) => {
if (blockNextClickRef.current) {
e.preventDefault();
e.stopPropagation();
blockNextClickRef.current = false;
return;
}
}, []);
const handlePress = useCallback((e: PressEvent) => {
if (e.pointerType === 'keyboard') {
blockNextClickRef.current = true;
}
}, []);
Item
```
### 🖥️ Steps to Reproduce
I was not able to reproduce the issue outside of my codebase, however I did my best to provide a similar context as my codebase (let me know how I can help): https://stackblitz.com/edit/tanstack-router-m5tec7wq?file=src%2Froutes%2F__root.tsx
### Version
1.14.0
### What browsers are you seeing the problem on?
Microsoft Edge
### If other, please specify.
All browsers
### What operating system are you using?
macOS
### 🧢 Your Company/Team
_No response_
### 🕷 Tracking Issue
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.