Skip to content

Commit 4969019

Browse files
authored
Fix useMenuItem onAction regression (#6807)
1 parent b8f5ac5 commit 4969019

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

packages/@react-aria/menu/src/useMenuItem.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ export function useMenuItem<T>(props: AriaMenuItemProps, state: TreeState<T>, re
133133

134134
if (item?.props?.onAction) {
135135
item.props.onAction();
136+
} else if (props.onAction) {
137+
props.onAction(key);
136138
}
137139

138140
if (data.onAction) {
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2020 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
import {AriaMenuProps, useMenu, useMenuItem} from '../';
14+
import {Item} from '@react-stately/collections';
15+
import {pointerMap, render} from '@react-spectrum/test-utils-internal';
16+
import React from 'react';
17+
import userEvent from '@testing-library/user-event';
18+
import {useTreeState} from '@react-stately/tree';
19+
20+
function Menu<T extends object>(props: AriaMenuProps<T> & {onSelect: () => void}) {
21+
// Create menu state based on the incoming props
22+
let state = useTreeState(props);
23+
24+
// Get props for the menu element
25+
let ref = React.useRef(null);
26+
let {menuProps} = useMenu(props, state, ref);
27+
28+
return (
29+
<ul {...menuProps} ref={ref}>
30+
{[...state.collection].map((item) => (
31+
<MenuItem key={item.key} item={item} state={state} onAction={props.onSelect} />
32+
))}
33+
</ul>
34+
);
35+
}
36+
37+
function MenuItem({item, state, onAction}) {
38+
// Get props for the menu item element
39+
let ref = React.useRef(null);
40+
let {menuItemProps, isSelected} = useMenuItem(
41+
{key: item.key, onAction},
42+
state,
43+
ref
44+
);
45+
46+
return (
47+
<li {...menuItemProps} ref={ref}>
48+
{item.rendered}
49+
{isSelected && <span aria-hidden="true"></span>}
50+
</li>
51+
);
52+
}
53+
54+
describe('useMenuTrigger', function () {
55+
let user;
56+
beforeAll(() => {
57+
user = userEvent.setup({delay: null, pointerMap});
58+
jest.useFakeTimers();
59+
});
60+
61+
afterEach(() => {
62+
});
63+
64+
it('calls an onAction passed directly to useMenuItem', async () => {
65+
let onSelect = jest.fn();
66+
let {getAllByRole} = render(
67+
<Menu onSelect={onSelect} aria-label={'test menu'}>
68+
<Item key="1">One</Item>
69+
<Item key="2">Two</Item>
70+
<Item key="3">Three</Item>
71+
</Menu>
72+
);
73+
let items = getAllByRole('menuitem');
74+
await user.click(items[0]);
75+
expect(onSelect).toHaveBeenCalledTimes(1);
76+
});
77+
});

0 commit comments

Comments
 (0)