react-native-paper
react-native-paper copied to clipboard
Menu component sometimes fails to render when rapidly toggling visibility
We’ve observed a bug in the Menu component where it intermittently fails to render when the visible state is toggled quickly. Specifically, calling setVisible(true) does not result in the menu appearing, even though the state is true. This leads to a confusing user experience where tapping the trigger does nothing visible, although the component believes it is in an open state.
This issue appears to be more prevalent under React Native’s Fabric renderer, and may be related to a layout or mounting race condition.
https://github.com/user-attachments/assets/74a474c8-9cc6-4f50-879e-940802ecb62e
System: OS: macOS 15.5 CPU: (12) arm64 Apple M3 Pro Memory: 777.98 MB / 36.00 GB Shell: version: "5.9" path: /bin/zsh Binaries: Node: version: 23.3.0 path: /usr/local/bin/node Yarn: version: 4.9.1 path: /usr/local/bin/yarn npm: version: 11.3.0 path: /usr/local/bin/npm Watchman: version: 2024.12.02.00 path: /opt/homebrew/bin/watchman Managers: CocoaPods: version: 1.16.2 path: /opt/homebrew/bin/pod SDKs: iOS SDK: Platforms: - DriverKit 24.4 - iOS 18.4 - macOS 15.4 - tvOS 18.4 - visionOS 2.4 - watchOS 11.4 Android SDK: Not Found IDEs: Android Studio: 2024.3 AI-243.24978.46.2431.13208083 Xcode: version: 16.3/16E140 path: /usr/bin/xcodebuild Languages: Java: version: 17.0.13 path: /opt/homebrew/opt/openjdk@17/bin/javac Ruby: version: 3.4.1 path: /opt/homebrew/opt/ruby/bin/ruby npmPackages: "@react-native-community/cli": Not Found react: Not Found react-native: Not Found react-native-macos: Not Found npmGlobalPackages: "react-native": Not Found Android: hermesEnabled: true newArchEnabled: true iOS: hermesEnabled: true newArchEnabled: true
this is the log
(NOBRIDGE) LOG [Menu] ✅ Layout valid, proceed to show
(NOBRIDGE) LOG 📐 [onLayout] Layout confirmed
(NOBRIDGE) LOG [Menu] 🖼 Rendering Menu
(NOBRIDGE) LOG ✅ [timeout] Layout confirmed in time
(NOBRIDGE) LOG [Menu] 🎬 Animation finished: true
(NOBRIDGE) LOG ❎ [onDismiss] Dismissing and resetting state
(NOBRIDGE) LOG [Menu] 🖼 Rendering Menu
(NOBRIDGE) LOG [Menu] 🔄 updateVisibility called: {"display": true, "prev": true}
(NOBRIDGE) LOG 📊 [state] visible = false
(NOBRIDGE) LOG [Menu] 🔄 updateVisibility called: {"display": false, "prev": true}
(NOBRIDGE) LOG [Menu] ⏹ hide()
(NOBRIDGE) LOG [Menu] ⏹ hide() called
(NOBRIDGE) LOG [Menu] 🎬 Animation finished (hide): true
(NOBRIDGE) LOG [Menu] 🧹 Cleaning up layout/render state
(NOBRIDGE) LOG [Menu] 🔍 Attempting to focus first DOM node (if any)
The Menu component from react-native-paper sometimes fails to properly call the onDismiss callback, especially under rapid visibility toggling. This results in external visible state being stuck as true, even though the menu has already visually disappeared.
🔍 Root Cause
Inside the hide() function, the menu fade-out is handled via:
Animated.timing(opacityAnimationRef.current, {
toValue: 0,
duration: ANIMATION_DURATION * animation.scale,
easing: EASING,
useNativeDriver: true,
}).start(({ finished }) => {
if (finished) {
setMenuLayout({ width: 0, height: 0 });
setRendered(false);
prevRendered.current = false;
focusFirstDOMNode(anchorRef.current);
// ✅ Always call onDismiss
onDismiss?.();
}
});
The problem is: onDismiss is only called when finished === true.
However, in real-world usage, especially when toggling visibility quickly (e.g., multiple setVisible(true) and setVisible(false) calls within a short period), the previous animation can be interrupted. When that happens: • The callback receives finished === false • onDismiss is not called • The external state (e.g., React state hook) remains true • This causes the Menu to become stuck and no longer visible, but also not dismissible
+1
Any solution ?
Same problem :/
Suffering with same problem
@Jianlong-Nie have you opened PR for this or has anyone?
Try to debounce the visibility toggle func for about 250ms as a workaround