Skip to content

Commit 78b2d75

Browse files
authored
fix(Menu): defer unmounting Portal until hide animation finishes (#4845)
* (fix): defer unmounting Portal until hide animation finishes * fix(menu): wait a tick before ensuring the component * fix(menu): add pointerEvents to snapshot styles
1 parent cbd4a6e commit 78b2d75

File tree

3 files changed

+21
-6
lines changed

3 files changed

+21
-6
lines changed

src/components/Menu/Menu.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ const Menu = ({
395395
return;
396396
}
397397

398-
if (!display && prevRendered.current) {
398+
if (!display) {
399399
hide();
400400
}
401401

@@ -430,15 +430,23 @@ const Menu = ({
430430
if (prevVisible.current !== visible) {
431431
prevVisible.current = visible;
432432

433-
if (visible !== rendered) {
434-
setRendered(visible);
433+
if (visible) {
434+
if (!rendered) {
435+
// Mount the Portal before attempting to show.
436+
setRendered(true);
437+
}
438+
} else {
439+
// Keep the Portal mounted so the hide animation can finish.
440+
updateVisibility(false);
435441
}
436442
}
437-
}, [visible, rendered]);
443+
}, [visible, rendered, updateVisibility]);
438444

439445
React.useEffect(() => {
440-
updateVisibility(rendered);
441-
}, [rendered, updateVisibility]);
446+
if (rendered && visible) {
447+
updateVisibility(true);
448+
}
449+
}, [rendered, visible, updateVisibility]);
442450

443451
// I don't know why but on Android measure function is wrong by 24
444452
const additionalVerticalValue = Platform.select({
@@ -639,6 +647,7 @@ const Menu = ({
639647
accessibilityLabel={overlayAccessibilityLabel}
640648
accessibilityRole="button"
641649
onPress={onDismiss}
650+
pointerEvents={visible ? 'auto' : 'none'}
642651
style={styles.pressableOverlay}
643652
/>
644653
<View

src/components/__tests__/Menu.test.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ it('uses the default anchorPosition of top', async () => {
131131
// itself.
132132
await act(async () => {
133133
screen.update(makeMenu(true));
134+
// Menu waits a tick for Portal refs to be up-to-date.
135+
await Promise.resolve();
134136
});
135137

136138
await waitFor(() => {
@@ -182,6 +184,8 @@ it('respects anchorPosition bottom', async () => {
182184

183185
await act(async () => {
184186
screen.update(makeMenu(true));
187+
// Menu waits a tick for Portal refs to be up-to-date.
188+
await Promise.resolve();
185189
});
186190

187191
await waitFor(() => {

src/components/__tests__/__snapshots__/Menu.test.tsx.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ exports[`renders menu with content styles 1`] = `
209209
onResponderTerminate={[Function]}
210210
onResponderTerminationRequest={[Function]}
211211
onStartShouldSetResponder={[Function]}
212+
pointerEvents="auto"
212213
style={
213214
{
214215
"bottom": 0,
@@ -933,6 +934,7 @@ exports[`renders visible menu 1`] = `
933934
onResponderTerminate={[Function]}
934935
onResponderTerminationRequest={[Function]}
935936
onStartShouldSetResponder={[Function]}
937+
pointerEvents="auto"
936938
style={
937939
{
938940
"bottom": 0,

0 commit comments

Comments
 (0)