Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions src/components/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,11 @@ const Menu = ({
easing: EASING,
useNativeDriver: true,
}),
]).start(() => {
focusFirstDOMNode(menuRef.current);
prevRendered.current = true;
]).start(({ finished }) => {
if (finished) {
focusFirstDOMNode(menuRef.current);
prevRendered.current = true;
}
});
});
}, [anchor, attachListeners, measureAnchorLayout, theme]);
Expand All @@ -371,6 +373,12 @@ const Menu = ({

const { animation } = theme;

// Reset before the animation starts so that the menu can be re-opened
// even if the hide animation's completion callback never fires (e.g. on
// React Native >= 0.80 where the animation `finished` event is not
// delivered). Without this the menu stays closed and cannot be shown again.
prevRendered.current = false;

Animated.timing(opacityAnimationRef.current, {
toValue: 0,
duration: ANIMATION_DURATION * animation.scale,
Expand All @@ -379,7 +387,6 @@ const Menu = ({
}).start(() => {
setMenuLayout({ width: 0, height: 0 });
setRendered(false);
prevRendered.current = false;
focusFirstDOMNode(anchorRef.current);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose, moving prevRendered.current = false before hide animation can introduce a race. if the menu closes while its opening animation is running, the interrupted opening callback can set this back to true, preventing the menu from reopening

could we handle interrupted opening & hiding animations using finished and add a test for quickly closing & reopening the menu?

}).start(({ finished }) => {
  if (!finished) {
    return;
  }
  setMenuLayout({ width: 0, height: 0 });
  setRendered(false);
  prevRendered.current = false;
  focusFirstDOMNode(anchorRef.current);
});

}, [removeListeners, theme]);
Expand Down