react-native-gesture-handler icon indicating copy to clipboard operation
react-native-gesture-handler copied to clipboard

Pressable stops working

Open vendramini opened this issue 7 months ago • 36 comments
trafficstars

Description

This is a really weird behavior, I've been facing it from time to time eventually - only on Android on both real devices and simulators.

I have a big and complex project, and sometimes it just stops receiving clicks on Pressable component.

Today I put some debugging on Pressable.tsx and I've found that isTouchPropagationAllowed.current is always false. The main function is:

const pressOutHandler = useCallback(
      (event: PressableEvent) => {
        console.log('pressOutHandler', isTouchPropagationAllowed.current)

        if (!isTouchPropagationAllowed.current) {
          hasPassedBoundsChecks.current = false;
          isPressCallbackEnabled.current = true;
          deferredEventPayload.current = null;

          if (longPressTimeoutRef.current) {
            clearTimeout(longPressTimeoutRef.current);
            longPressTimeoutRef.current = null;
          }

          if (pressDelayTimeoutRef.current) {
            clearTimeout(pressDelayTimeoutRef.current);
            pressDelayTimeoutRef.current = null;
          }

          return;
        }

        if (
          !hasPassedBoundsChecks.current ||
          event.nativeEvent.touches.length >
            event.nativeEvent.changedTouches.length
        ) {
          return;
        }

        if (unstable_pressDelay && pressDelayTimeoutRef.current !== null) {
          // When delay is preemptively finished by lifting touches,
          // we want to immediately activate it's effects - pressInHandler,
          // even though we are located at the pressOutHandler
          clearTimeout(pressDelayTimeoutRef.current);
          pressInHandler(event);
        }

        if (deferredEventPayload.current) {
          onPressIn?.(deferredEventPayload.current);
          deferredEventPayload.current = null;
        }

        onPressOut?.(event);

        if (isPressCallbackEnabled.current) {
          onPress?.(event);
        }

        if (longPressTimeoutRef.current) {
          clearTimeout(longPressTimeoutRef.current);
          longPressTimeoutRef.current = null;
        }

        console.log(4);

        isTouchPropagationAllowed.current = false;
        hasPassedBoundsChecks.current = false;
        isPressCallbackEnabled.current = true;
        setPressedState(false);
      },
      [onPress, onPressIn, onPressOut, pressInHandler, unstable_pressDelay]
    );

As being false its execution stops on the first condition, not firing onPress.

I couldn't reproduce it in a repro, but it is happening often on my project.

My _layout.tsx:

return (
    <GestureHandlerRootView style={{flex: 1}}>
      <LoaderFullscreen>
        <trpc.Provider client={trpcClient} queryClient={queryClient}>
          <CustomConfirmationBottomSheetModalProvider>
            <CustomBottomSheetModalProvider>
              <ThemeProvider value={DefaultReactNavigationTheme}>
                <CustomQueryClientProvider>
                  <KeyboardProvider statusBarTranslucent>
                    <SafeAreaProvider initialMetrics={initialWindowMetrics}>
                      <AuthProvider>
                        <App />
                      </AuthProvider>
                    </SafeAreaProvider>
                  </KeyboardProvider>
                </CustomQueryClientProvider>
              </ThemeProvider>
            </CustomBottomSheetModalProvider>
          </CustomConfirmationBottomSheetModalProvider>
        </trpc.Provider>
      </LoaderFullscreen>
      {toastContent}
    </GestureHandlerRootView>
  );

As a temporary (I hope) solution, I'll have to use <GestureDetector gesture={singleTap}> on each clickable spot and handle it manually. That way it always works.

Steps to reproduce

  1. Just open my app and try clicking on some buttons. It doesn't happen all the time, but quite often.

Snack or a link to a repository

I couldn't reproduce it.

Gesture Handler version

2.25.0

React Native version

0.77.1

Platforms

Android

JavaScript runtime

Hermes

Workflow

Expo managed workflow

Architecture

Paper (Old Architecture)

Build type

Release mode

Device

Real device

Device model

Moto g60

Acknowledgements

Yes

vendramini avatar Apr 05 '25 18:04 vendramini

When this issue occur I usually change to Pressable from react-native. It turns out that it has already happened before with it (Pressable from RN), then I switched to RNGH. Now it started happening with it.

Sorry about not being able to reproduce it in an isolated project, but it is just not happening - but it does happen on my project.

Happy to debug together with you guys.

vendramini avatar Apr 05 '25 20:04 vendramini

@vendramini I have the same issue as well. Are you using expo-router/react-navigation/react-native-screens? For me, the issue occurs when Flatlist/Flashlists are on screen, it seems.

shovel-kun avatar Apr 07 '25 11:04 shovel-kun

@shovel-kun Yes, I'm using expo-router/react-navigation/react-native-screens, and yes, there are FlashList on the screen. However, it has already happened on screen that don't have FlashList on it.

This issue is so mysterious, I don't know what to do. Looking carefully on my project, I'm not doing anything wrong I guess. Everything is simple (although it's a big project), nothing but FlashList, buttons, texts, a default (tab) menu, some <Stacks/>. Basically a bunch of forms.

To make things worse, it happens from time to time without any apparently reason, then I have to swap from Pressable to Pressable, sometimes TouchableOpacity. Can't get it.

Were you able to isolate and reproduce the problem?

vendramini avatar Apr 07 '25 13:04 vendramini

Hey, could you please let me know if this issue also occurs on RNGH 2.24.0? We've made some changes to pressOutHandler in RNGH 2.25.0 that could be the cause of this bug.

latekvo avatar Apr 07 '25 13:04 latekvo

I have also been having the issue occasionally since swapping out all of the RN Pressable components in my app with the RNGH version (using 2.25.0). It almost seems like a gesture is getting "stuck" as the Pressable sometimes stays in a pressed state (different background color). When the issue occurs I have to restart the entire app to get back into a good state. I use react-navigation and the RNGH FlatList component on most screens so that could certainly be related.

One thing that did seem to make a difference for me - I had a PressableWithoutFeedback component covering the entire screen to catch things like taps outside of a modal. Although it was disabled, after removing it I'm not experiencing the issue much anymore. Maybe unrelated but there seemed to be a correlation.

iankberry avatar Apr 07 '25 13:04 iankberry

@latekvo you right! On 2.24.0 it doesn't occur. However, it is not working my pressed style on 2.24.0 (it does work on 2.25.0):

<Pressable style={styles.pressable} hitSlop={10} {...buttonProps}>
//stuff
</Pressable>

const stylesheet = createStyleSheet(({ colors }) => ({
  pressable: ({ pressed }: { pressed: boolean }) => ({
    opacity: pressed ? 0.5 : 1,
  }),
}));

It also feels more fluid and the touch seems to respond faster on 2.24.0.

@shovel-kun @iankberry would you guys please do the same and test on 2.24.0?

vendramini avatar Apr 07 '25 13:04 vendramini

I was able to reproduce the issue on 2.24.0 with some aggressive tapping. It definitely was easier to reproduce before. You can see ~23 seconds in the video one of the list items gets "stuck" in a pressed state and then all pressables completely stop responding after navigating into the details screen.

https://www.dropbox.com/scl/fi/g985jb3nlzetunaze6j4b/Screen-Recording-2025-04-07-at-10.35.51-AM.mov?rlkey=xrd6i0h4nd3rd09z889c5o5qf&dl=0

iankberry avatar Apr 07 '25 14:04 iankberry

@iankberry thanks for providing the video! Your issue seems most likely related to this one. I think there's a low chance it's related to the one reported by @vendramini, but I could be wrong.

Unfortunately, we haven't found any workarounds or fixes for this issue yet, but I'll keep you updated if we do find anything.

latekvo avatar Apr 07 '25 15:04 latekvo

@latekvo That's certainly possible, it seems to surface when paired with scrolling. I'll go ahead and subscribe to that issue then. I greatly appreciate you looking into this and your contribution to this fantastic library!

iankberry avatar Apr 07 '25 15:04 iankberry

Ah, I think the bug I'm facing is related to #3350

shovel-kun avatar Apr 07 '25 16:04 shovel-kun

I have the same issue as well

Unuuuuu avatar Apr 16 '25 06:04 Unuuuuu

I am using Expo 52, React Native 0.77.1 and react-native-gesture-handler 2.25.0 I have the same issue, but only on development builds. Release builds work without issues. If you must use react-native-gesture-handler buttons I suggest you try building a release variant and see if they work, otherwise I use regular react-native buttons when there is no need to use this library (for example, I found out that modals and bottom sheets work better with gesture handler buttons, and that is about it where they are beneficial). This inconsistency and mixing button libraries in one project very messy. I hope this gets fixed because Expo and React Native push the usage of this library, and many third party libraries rely on it, so we don't really have the option to not use it.

Edit: Actually, the same issue happens on release builds too, only rarely. I just now realised that after extensive testing of every button (I use both Pressables and BorderlessButtons from gesture handler library). It is impossible to reproduce because they stop working for unknown reasons. I tried 2.25.0, 2.24.0 and 2.23.0 - the issue is present everywhere.

eetzuh avatar Apr 16 '25 08:04 eetzuh

I'm using Expo 52, React Native 0.76 and RNGH 2.25. I'm experiencing the same issue. Pressable doesn't seam to work inside lists.

hwildwood avatar Apr 20 '25 16:04 hwildwood

it does works in v2.23.0 but after the list has stopped scrolling there is a few milliseconds delay before the pressable registers user click, thus many times resulting in having to click the same pressable two times so it can execute the onPress callback

SumitR9910 avatar Apr 21 '25 15:04 SumitR9910

I’m also experiencing this with expo 52, react native 0.77, and all the versions of gesture handler. Pressable inside of a Flatlist stop working randomly on android. I think it is maybe related to when I use scrollTo to move through the Flatlist?

atambo avatar Apr 24 '25 01:04 atambo

Also experiencing this. The Pressable component works great, apart from when it's within BottomSheetModal from @gorhom/bottom-sheet (version 4.6.4). Then it is really unresponsive.

Using the inbuilt react-native Pressable component fixes this in the meantime.

mattlennon3 avatar Apr 25 '25 12:04 mattlennon3

It can be a misunderstanding of mine, specially because I have no idea how RN works in practice (I know the theory, but not the implementation challenges), but doesn't it sound worry (sad) that the core library react-native itself can't make a simple functional button (a button!) that fits all needs and scenarios? They have to rely on some third-party library, that also face the same issue.

I'm not complaining nor judging you guys, serious, don't take that way. I've been using RN and RNGH for years. My comment here is more like "we are building products on top of it. Isn't it dangerous? How can we push a technology that faces simple problems?". Again, "simple problems" from the point of view of those who are consuming the API. Maybe it can be really hard to make it work without issues.

Does anyone know any articles or youtube video that go deep and show the challenges and issues of RN and why these kind of thing happen so often?

vendramini avatar Apr 26 '25 12:04 vendramini

My good friend @vendramini we find ourselves again in the corners of the internet!

I am also facing the exact same issue.

rafa-hover avatar May 02 '25 17:05 rafa-hover

I sometimes think it's a react modal or modal "thing" that wasn't closed properly but you navigate away from where that modal was, perhaps programmatically. It results in some sort of freeze on new screens and there's simply no way to recover from it othan than to restart the app. From what I see in my app it seems to still feel like it's operating, as no drops on fps or performance has occured but yet it's still "frozen" and unresponsive. I do agree with the sentiment of it occuring in scroll views of any sort.

qwalker8408 avatar May 03 '25 18:05 qwalker8408

I have same issue in project for android release builds. Its happen when I upgraded deps: react-native: 0.73.9 -> 0.78.2, react-native-gesture-handler: 2.19.0 -> 2.25.0

KCherkalov avatar May 12 '25 09:05 KCherkalov

Here is a repository to reproduce the issue : https://github.com/baylesa-dev/PressableIssue

On iOS, it does not work in a rngh FlatList nor in a rngh Scrollview, but works well outside of the list or in a react-native list.

function App(): React.JSX.Element {
    const renderItem = useCallback(
        ({item}: ListRenderItemInfo<(typeof fakeUsers)[0]>) => (
            <Pressable
                style={styles.listItem}
                onPress={() => console.log('Item Pressed!')}> // it does not work
                <Text>{item.name}</Text>
            </Pressable>
        ),
        [],
    );

    return (
        <GestureHandlerRootView>
            <View style={styles.container}>
                <Pressable
                    style={styles.card}
                    onPress={() => console.log('Card Pressed!')}> // it works !
                    <View>
                        <Text style={styles.text}>Hello World</Text>
                    </View>
                </Pressable>

                <FlatList
                    style={styles.list}
                    data={fakeUsers}
                    renderItem={renderItem}
                />
            </View>
        </GestureHandlerRootView>
    );
}

baylesa-dev avatar May 12 '25 11:05 baylesa-dev

Also facing some Pressables barely even being responsive. This occured after upgrading from 2.24 to 2.25. Seems like the issue was introduced there. For me this issue mainly occurs on iOS and creating a release build did not fix this for me the issue just occurs a bit less often.

a-klotz-p8 avatar May 22 '25 12:05 a-klotz-p8

The issue on iOS seems to be cause by this change: #3295. Maybe someone can investigate further from here.

a-klotz-p8 avatar May 22 '25 12:05 a-klotz-p8

Fwiw I realized on my side the issue was caused by this bug in Reanimated : https://github.com/software-mansion/react-native-reanimated/issues/7109 causing exiting animations not to unmount components. I still have issues with onPressIn sometimes not firing until releasing touch though, don't know if this is related.

Maniae avatar May 22 '25 13:05 Maniae

Hey! 👋

The issue doesn't seem to contain a minimal reproduction.

Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?

Repro repo: https://github.com/baylesa-dev/PressableIssue

baylesa-dev avatar May 26 '25 06:05 baylesa-dev

Would the maintainers be interested in sponsorship to fix these issues (on iOS and Android)? This is a really big problem for us and it's been affecting our app for quite some time now.

techied avatar Jun 05 '25 16:06 techied

I believe this is a minimal reproduction: https://github.com/baylesa-dev/PressableIssue

I would also be willing to monetarily sponsor a fix to this issue.

atambo avatar Jun 05 '25 17:06 atambo

Reverting the changes in this PR https://github.com/software-mansion/react-native-gesture-handler/pull/3295 using patch-package fixed the issue for me.

gigobyte avatar Jun 09 '25 14:06 gigobyte

Reverting the changes in this PR #3295 using patch-package fixed the issue for me.

That's also what I observed

a-klotz-p8 avatar Jun 10 '25 05:06 a-klotz-p8

Reverting the changes in this PR #3295 using patch-package fixed the issue for me.

Same, but it brings back the nested Pressables issue.

fsvapat avatar Jun 11 '25 21:06 fsvapat