Reach-ui: MenuButton: Cannot read property 'focus' of undefined

Created on 8 Jun 2019  路  9Comments  路  Source: reach/reach-ui

Encountering an issue with MenuButton throwing a Cannot read property 'focus' of undefined error after hovering with the mouse, moving the mouse out of the Menu and then hitting the up arrow on the keyboard. The same error is not thrown when hitting the down arrow. The issue is observable in the current docs. Gif attached.

ReachMenuFocusError

Enhancement

Most helpful comment

All 9 comments

My initial investigation looks like the issue is caused here:
https://github.com/reach/reach-ui/blob/master/packages/menu-button/src/index.js#L391

After the blur state.selectionIndex is already -1 so the if (nextIndex !== -1) block is called with nextIndex = -2.

Happy to submit a PR, I'm just not sure what the intended behavior should be. When no item is selected and the user hits the up arrow which item should be selected? The first item? I don't see any specific rules in the ARIA guidelines governing this case but:

When a menu opens, or when a menubar receives focus, keyboard focus is placed on the first item.

...would seem like the most relevant rule.

Checked what the logic on Chrome dropdown is:

Jun-12-2019 11-38-152

Moving mouse anywhere resets keyboard control to initial state

Cool, thanks for that @qoalu. @ryanflorence would you accept a PR that implements the above behavior to fix the issue?

I think I'm having the same issue in a test using jest + react testing library.

Unfortunately, I wasn't able to reproduce this issue in a codesandbox yet and I also don't see the error in my app. In the test, I'm getting the MenuButton by it's data attribute, clicking it via fireEvent.click(menuButton) and then assert the DOM. The error occurs only sometimes as another test, doing the exact same thing, works fine 馃槙

Edit: Is it the same error though? I just realized that my error is thrown because of a value being null instead of undefined.

TypeError: Cannot read property 'focus' of null
  at focus (../../node_modules/@reach/menu-button/index.js:67:42)

@ReasonableDeveloper I am having the exact same issue as you with react-testing-library

My failed attempt of reproducing the error in a codesandbox can be found here

Unfortunately, all the tests are passing in the codesandbox but failing in my project. At this point, I'm uncertain if the problem is related to jsdom, reach-ui or react-testing library.

Edit: If you download the codesandbox and run yarn && yarn test, you can see the error.

also @CodingDive to temporally fix your tests until my pull request is merged you can add something like this to mock the requestAnimationFrame. I hate adding timeouts and this is just a "bandaid solution" but it works for now.

  beforeEach(() => {
    jest.spyOn(window, 'requestAnimationFrame').mockImplementation(cb => {
      return setTimeout(cb, 200);
    });
  });

I can repro in @CodingDive's sandbox by:

  1. Clicking to open the MenuButton
  2. With the cursor inside the MenuList, use any arrow keys
  3. Move the cursor over a MenuItem and away such that no items are selected
  4. Move the cursor outside the MenuList and hit the _up_ arrow key again (seems to be up only?)
  5. 馃挜
Was this page helpful?
0 / 5 - 0 ratings