From 496901973403f28559823e31d1a8daf29ddd4966 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Mon, 5 Aug 2024 11:01:39 +1000 Subject: [PATCH] Fix useMenuItem onAction regression (#6807) --- packages/@react-aria/menu/src/useMenuItem.ts | 2 + .../@react-aria/menu/test/useMenu.test.tsx | 77 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 packages/@react-aria/menu/test/useMenu.test.tsx diff --git a/packages/@react-aria/menu/src/useMenuItem.ts b/packages/@react-aria/menu/src/useMenuItem.ts index 90a999b5a9e..aa19c17f7d4 100644 --- a/packages/@react-aria/menu/src/useMenuItem.ts +++ b/packages/@react-aria/menu/src/useMenuItem.ts @@ -133,6 +133,8 @@ export function useMenuItem(props: AriaMenuItemProps, state: TreeState, re if (item?.props?.onAction) { item.props.onAction(); + } else if (props.onAction) { + props.onAction(key); } if (data.onAction) { diff --git a/packages/@react-aria/menu/test/useMenu.test.tsx b/packages/@react-aria/menu/test/useMenu.test.tsx new file mode 100644 index 00000000000..aafb79204c3 --- /dev/null +++ b/packages/@react-aria/menu/test/useMenu.test.tsx @@ -0,0 +1,77 @@ +/* + * Copyright 2020 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {AriaMenuProps, useMenu, useMenuItem} from '../'; +import {Item} from '@react-stately/collections'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; +import React from 'react'; +import userEvent from '@testing-library/user-event'; +import {useTreeState} from '@react-stately/tree'; + +function Menu(props: AriaMenuProps & {onSelect: () => void}) { + // Create menu state based on the incoming props + let state = useTreeState(props); + + // Get props for the menu element + let ref = React.useRef(null); + let {menuProps} = useMenu(props, state, ref); + + return ( +
    + {[...state.collection].map((item) => ( + + ))} +
+ ); +} + +function MenuItem({item, state, onAction}) { + // Get props for the menu item element + let ref = React.useRef(null); + let {menuItemProps, isSelected} = useMenuItem( + {key: item.key, onAction}, + state, + ref + ); + + return ( +
  • + {item.rendered} + {isSelected && } +
  • + ); +} + +describe('useMenuTrigger', function () { + let user; + beforeAll(() => { + user = userEvent.setup({delay: null, pointerMap}); + jest.useFakeTimers(); + }); + + afterEach(() => { + }); + + it('calls an onAction passed directly to useMenuItem', async () => { + let onSelect = jest.fn(); + let {getAllByRole} = render( + + One + Two + Three + + ); + let items = getAllByRole('menuitem'); + await user.click(items[0]); + expect(onSelect).toHaveBeenCalledTimes(1); + }); +});