react-native-paper icon indicating copy to clipboard operation
react-native-paper copied to clipboard

Menu can only be opened once on expo 54 / RN 0.81

Open LiamMorrow opened this issue 3 months ago • 29 comments

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch [email protected] for the project I'm working on. I noticed that the Menu component in expo 54 (RN 0.81) can only be opened once, then it stays closed. This affects both iOS and Android. For some reason I noticed that the finished flag was always false on the hide callback, I'm unsure why this would be. This patch isn't perfect, it now seems like animations only work the first time, however it at least opens and closes fine.

Video of bug

https://github.com/user-attachments/assets/1272df15-bc65-4034-992e-bd07a7c5f186

Video of patched version (no animations after first, but at least opens)

https://github.com/user-attachments/assets/b4419fe7-ef02-4c93-a2db-2dc0c326803b

Here is the diff that solved my problem:

diff --git a/node_modules/react-native-paper/src/components/Menu/Menu.tsx b/node_modules/react-native-paper/src/components/Menu/Menu.tsx
index 55922c1..9b53403 100644
--- a/node_modules/react-native-paper/src/components/Menu/Menu.tsx
+++ b/node_modules/react-native-paper/src/components/Menu/Menu.tsx
@@ -359,11 +359,9 @@ const Menu = ({
         easing: EASING,
         useNativeDriver: true,
       }),
-    ]).start(({ finished }) => {
-      if (finished) {
-        focusFirstDOMNode(menuRef.current);
-        prevRendered.current = true;
-      }
+    ]).start(() => {
+      focusFirstDOMNode(menuRef.current);
+      prevRendered.current = true;
     });
   }, [anchor, attachListeners, measureAnchorLayout, theme]);
 
@@ -377,13 +375,11 @@ const Menu = ({
       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);
-      }
+    }).start(() => {
+      setMenuLayout({ width: 0, height: 0 });
+      setRendered(false);
+      prevRendered.current = false;
+      focusFirstDOMNode(anchorRef.current);
     });
   }, [removeListeners, theme]);
 

This issue body was partially generated by patch-package.

LiamMorrow avatar Sep 17 '25 01:09 LiamMorrow

I also encountered the issue in Expo 54 where the menu can only be opened once. However, the problem with the transition animation only working the first time has been around for a while and doesn't seem to have been introduced by the Expo 54 update.

Btw, I tried your patch, and it works!

roitium avatar Sep 17 '25 11:09 roitium

+1

RohovDmytro avatar Sep 17 '25 15:09 RohovDmytro

Happening to me as well, same setup.

gogupaul123 avatar Sep 17 '25 16:09 gogupaul123

+1, I noticed this issue affecting https://github.com/fateh999/react-native-paper-dropdown. Hoping for a quick fix!

shoffing avatar Sep 19 '25 02:09 shoffing

+1, I applied the patch to fix the exact same issue on RN 0.80 (without Expo).

alemar11 avatar Sep 19 '25 08:09 alemar11

btw, the patch fix is working.

RohovDmytro avatar Sep 19 '25 10:09 RohovDmytro

wow spent a good couple hours trying to debug and just seen this, feel silly. will try the patch 👌

samuelbadru avatar Sep 19 '25 20:09 samuelbadru

I believe it's also necessary to patch the file inside lib/module for it to work in production. If you're using Expo, you can test this by running npx expo start --no-dev --minify

JameDodgers avatar Sep 19 '25 23:09 JameDodgers

I believe it's also necessary to patch the file inside lib/module for it to work in production. If you're using Expo, you can test this by running npx expo start --no-dev --minify

Yeah it's definitely interesting. I'm not sure why but my app uses the typescript sources of this lib when building/running

LiamMorrow avatar Sep 20 '25 00:09 LiamMorrow

+1

icedevml avatar Sep 20 '25 01:09 icedevml

+1, I noticed this issue affecting https://github.com/fateh999/react-native-paper-dropdown. Hoping for a quick fix!

I believe this library is no longer maintained since there last update is more than a year ago, and it's sole maintainer is fateh999 himself

Bk49 avatar Sep 22 '25 03:09 Bk49

+1 patch does work as what the developer has mentioned. For anyone wondering how to work with patch package

  1. npm i -D patch-package postinstall-postinstall
  2. Create a new directory patches where you have your package.json
  3. Add the following file to the directory
  4. Add a new script to you package.json => "postinstall": "patch-package",
  5. Commit it to Github

react-native-paper+5.14.5.patch

For bun users

  1. npm i first to create a lock file
  2. Follow the steps above

If directly using the file doesn't work...

  1. After following step 1 of the first set of instructions, navigate to node_modules/react-native-paper/src/components/Menu/Menu.tsx
  2. Replace line 359+ and 377+ like how the owner of this issue did (Necessary for development)
  3. Replace line 235+ and 254+ like how the owner of this issue did (Necessary for production)
  4. Run npx patch-package react-native-paper

Bk49 avatar Sep 22 '25 04:09 Bk49

It looks like the patch still breaks sometimes for some reason?

https://github.com/user-attachments/assets/df251fcf-3967-4c7e-864d-4ff3c3164f46

banddans avatar Sep 25 '25 08:09 banddans

It looks like the patch still breaks sometimes for some reason?

Skarminspelning.2025-09-25.kl.10.07.42.mov

Yup I am having the same issue even tho I have applied the patch to fix the exact same issue

arshvinw5 avatar Sep 28 '25 19:09 arshvinw5

+1

tux2nicolae avatar Sep 30 '25 15:09 tux2nicolae

+1

nisnardi avatar Oct 01 '25 20:10 nisnardi

i'd start logging rendered, visible and prevRendered.current.

if ur setting the menu's visible via ondismiss, check out https://github.com/callstack/react-native-paper/issues/4813

for the opening animation checkout https://github.com/callstack/react-native-paper/issues/4812

lovegaoshi avatar Oct 01 '25 20:10 lovegaoshi

Changing the menu key solved it for me without having to change library code.

P.S.: This is a temporary workaround.

const [menuKey, setMenuKey] = useState(0);

<Menu
  key={menuKey}
  visible={visible}
  onDismiss={() => {
    setVisible(false);
    setMenuKey(k => k + 1);
  }}

/>

johnnymakhoul avatar Oct 06 '25 08:10 johnnymakhoul

Changing the menu key solved it for me without having to change library code.

P.S.: This is a temporary workaround.

const [menuKey, setMenuKey] = useState(0);

<Menu
  key={menuKey}
  visible={visible}
  onDismiss={() => {
    setVisible(false);
    setMenuKey(k => k + 1);
  }}

/>

Not great to use a separate state for this, as it triggers reconciliation

Bk49 avatar Oct 06 '25 10:10 Bk49

Changing the menu key solved it for me without having to change library code. P.S.: This is a temporary workaround.

const [menuKey, setMenuKey] = useState(0);

<Menu
  key={menuKey}
  visible={visible}
  onDismiss={() => {
    setVisible(false);
    setMenuKey(k => k + 1);
  }}

/>

Not great to use a separate state for this, as it triggers reconciliation

using useRef can solve this

johnnymakhoul avatar Oct 06 '25 11:10 johnnymakhoul

Changing the menu key solved it for me without having to change library code.

P.S.: This is a temporary workaround.


<Menu
  key={visible}
  visible={visible}
  onDismiss={() => {
    setVisible(false);
  }}

/>

You can use the same value on the key as it is on visible, that works for me, and no need for extra state

bpavlicTMF avatar Oct 06 '25 11:10 bpavlicTMF

This works (Typescript)

const [isMenuVisible, setIsMenuVisible] = useState<boolean>(false);

<Menu
    key={Boolean(isMenuVisible) as unknown as React.Key}
    visible={isMenuVisible}
    onDismiss={() => setIsMenuVisible(false)}
    anchor={
      <MaterialCommunityIcons
        color="#fff"
        name="sort"
        size={22}
        onPress={() => setIsMenuVisible(true)}
      />
    }
  >
    <Menu.Item
      onPress={() => {}}
      title="Item"
    />
  </Menu>

musasoftlabx avatar Oct 13 '25 08:10 musasoftlabx

@musasoftlabx For TS you can just do key={String(isMenuVisible)}

bpavlicTMF avatar Oct 13 '25 10:10 bpavlicTMF

@musasoftlabx For TS you can just do key={String(isMenuVisible)}

Can confirm that this works, thanks

gogupaul123 avatar Oct 13 '25 14:10 gogupaul123

I've also had this issue, thank you so much, adding key={String(isMenuVisible)} fixes the issue for me.

bobbotron avatar Oct 19 '25 00:10 bobbotron

i'd start logging rendered, visible and prevRendered.current.

if ur setting the menu's visible via ondismiss, check out #4813

for the opening animation checkout #4812

This ^^ worked for me.

a-ghorbani avatar Oct 19 '25 14:10 a-ghorbani

+1 patch does work as what the developer has mentioned. For anyone wondering how to work with patch package

  1. npm i -D patch-package postinstall-postinstall
  2. Create a new directory patches where you have your package.json
  3. Add the following file to the directory
  4. Add a new script to you package.json => "postinstall": "patch-package",
  5. Commit it to Github

react-native-paper+5.14.5.patch

For bun users

  1. npm i first to create a lock file
  2. Follow the steps above

If directly using the file doesn't work...

  1. After following step 1 of the first set of instructions, navigate to node_modules/react-native-paper/src/components/Menu/Menu.tsx
  2. Replace line 359+ and 377+ like how the owner of this issue did (Necessary for development)
  3. Replace line 235+ and 254+ like how the owner of this issue did (Necessary for production)
  4. Run npx patch-package react-native-paper

I had to update commonjs file as well; see here: https://github.com/callstack/react-native-paper/issues/4763#issuecomment-3427895632

alexkev avatar Oct 21 '25 17:10 alexkev

key={Boolean(isMenuVisible) as unknown as React.Key}

Amazing, bro. Thanks a lot. It solved a month problem. same for you @bpavlicTMF .

Reidevl avatar Oct 23 '25 00:10 Reidevl

@musasoftlabx For TS you can just do key={String(isMenuVisible)}

This worked for me. Simple workaround without patch release

nagapakalapati avatar Oct 28 '25 22:10 nagapakalapati

Changing the menu key solved it for me without having to change library code. P.S.: This is a temporary workaround.


<Menu
  key={visible}
  visible={visible}
  onDismiss={() => {
    setVisible(false);
  }}

/>

You can use the same value on the key as it is on visible, that works for me, and no need for extra state

Worked for me also. Thank you !

Nikosbatz avatar Dec 13 '25 22:12 Nikosbatz