facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
119.57k stars 24.37k forks source link

Touchable components stop responding randomly #36710

Closed vrgimael closed 8 months ago

vrgimael commented 1 year ago

Description

We've been experiencing this issue in a couple of our apps, it's kinda driving us mad.

Basically, sometimes, completely unpredictably the touchable areas just stop responding.

We tried reproducing this consistently in several different ways but just couldn't pin point what causes it to happen and in which devices. It happens on both iOS and Android, and also in debug or release mode. Generally, it looks like it only happens after the user has been using the app for a little while (10+ minutes). It seems to happen in any button in the app randomly, and some times it also seemingly randomly starts working again. Closing and opening the app again always fixes the problem.

We had clients complain about it in quite a few occasion, but some of our public testers rarely ever experience this either which makes it even harder to understand.

I spent a very long time investigating it over literally the past entire year, but it's really really hard to debug, because when the issue happens in debug mode, anything you do in the code that causes hot reloading actually "fixes it", making it almost impossible to investigate.

I have added lots of debugging tools to try and understand what happens though, I got a few bits of information that might be able to help.

  1. This is not a performance or execution queue issue, as we have other interactive components in the screen that update automatically based on time and these never freeze.
  2. Other touch based components seem to continue working like scrolls or maps.
  3. The zindex of the buttons I'm trying to interact with is much greater than anything else in the screen.
  4. I have tried swapping out our "button" component's touchable with react-native-gesture-handler's, but the issue still persists.
  5. This has been going for several different versions of RN and none resolved.
  6. When the issue happens, the onPressIn and onPressOut events are fired almost simultaneously with only a few milliseconds difference but onPress is not fired - kinda like what happens when you're scrolling or actually interacting with another gesture handler. I tried to make a fallback mechanism that uses this behaviour to our advantage but it's outcome is not very consistent for a few different reasons.
  7. Surprisingly (and this is what makes me think it's an issue with RN and not our code), when this issue happens and you manage to open the RN inspect menu by shaking the device, the tabs in the menu (Inspect, Perf, Network, Touchables) don't even work, exactly the same behaviour observed with our own buttons in the app.
  8. It might be out of pure coincidence, but I have only seen this happen in apps that use react-native-maps - one of my hypothesis is that the gesture responder somehow gets confused with the map handler.

As far as I can tell, this has always happened - it's so rare that I was not very bothered by it. But as our apps grow and have a larger userbase now, this issue is coming up more frequently and we need to figure it out some time soon. I suspect this is not too much of a problem in other apps because normally if a problem like this happens you'd just reopen the app and everything is fine again. However, it has already caused bad reviews in the App Store because our app's functionality is really time sensitive and if users aren't able to interact with the screen it's kinda problematic.

I've read all issues related to several relevant keywords in this repo (like touchable, onpressin, not responding, etc...), and there are a few issues that mention similar behaviour https://github.com/facebook/react-native/issues/34999 https://github.com/facebook/react-native/issues/36063 but none have barely any responses (possibly due to the rare nature of the problem).

Any help would be really appreciated. Please let me know if I can provide any other useful information.

Thanks

React Native Version

0.70.6

Output of npx react-native info

System: OS: macOS 13.2.1 CPU: (10) arm64 Apple M1 Max Memory: 192.88 MB / 32.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 16.13.0 - ~/.nvm/versions/node/v16.13.0/bin/node Yarn: 1.19.1 - ~/.yarn/bin/yarn npm: 7.24.2 - ~/CodeLeap-Software/Client-Projects/x-follo-mobile/mobile/node_modules/.bin/npm Watchman: 2022.07.04.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.11.3 - /opt/homebrew/bin/pod SDKs: iOS SDK: Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1 Android SDK: API Levels: 26, 28, 29, 30, 31, 33 Build Tools: 28.0.3, 29.0.2, 30.0.2, 30.0.3, 31.0.0, 32.0.0, 33.0.0 System Images: android-30 | Google Play ARM 64 v8a, android-31 | ARM 64 v8a, android-31 | Google APIs ARM 64 v8a, android-31 | Google Play ARM 64 v8a, android-Sv2 | Google APIs ARM 64 v8a, android-Sv2 | Google Play ARM 64 v8a Android NDK: 22.1.7171670 IDEs: Android Studio: 2020.3 AI-203.7717.56.2031.7784292 Xcode: 14.2/14C18 - /usr/bin/xcodebuild Languages: Java: 11.0.13 - /Users/victor/Library/Java/JavaVirtualMachines/azul-11.0.13/Contents/Home/bin/javac npmPackages: @react-native-community/cli: Not Found react: ^18.2.0 => 18.2.0 react-native: ^0.70.6 => 0.70.7 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found

Steps to reproduce

The hardest thing about this is that it can't be reliably reproduced. See description above.

Snack, code example, screenshot, or link to a repository

Example in our own app (that's in the App Stores too), a client sent us this recording of it happening in practice. Looking back now I should have taken more recordings of it but I'm not sure it would be of any use too.

https://user-images.githubusercontent.com/14969223/228675821-fb9b1eac-7228-4276-85ce-5d1c2bf2f284.mp4

EDIT 30/05/23 -> Here are the dependencies for this project:

  "dependencies": {
    "@babel/plugin-proposal-export-namespace-from": "^7.18.9",
    "@babel/runtime": "^7.14.6",
    "@faker-js/faker": "^7.3.0",
    "@googlemaps/polyline-codec": "^1.0.1",
    "@invertase/react-native-apple-authentication": "^2.2.2",
    "@miblanchard/react-native-slider": "^2.3.1",
    "@react-native-async-storage/async-storage": "~1.17.3",
    "@react-native-community/netinfo": "^9.3.6",
    "@react-native-community/push-notification-ios": "^1.10.1",
    "@react-native-firebase/analytics": "^15.2.0",
    "@react-native-firebase/app": "^15.2.0",
    "@react-native-firebase/auth": "^15.2.0",
    "@react-native-firebase/crashlytics": "^15.2.0",
    "@react-native-firebase/messaging": "^15.2.0",
    "@react-native-google-signin/google-signin": "^8.0.0",
    "@react-native-masked-view/masked-view": "^0.2.8",
    "@react-navigation/bottom-tabs": "^6.3.2",
    "@react-navigation/native": "^6.0.11",
    "@react-navigation/stack": "^6.2.2",
    "@sentry/react-native": "^3.1.1",
    "callsites": "^3.1.0",
    "date-fns": "^2.29.2",
    "deep-equal": "^2.0.5",
    "deep-object-diff": "^1.1.9",
    "deprecated-react-native-prop-types": "^2.3.0",
    "expo": "^48.0.6",
    "expo-av": "^13.0.2",
    "expo-battery": "^7.0.0",
    "expo-cellular": "^5.0.1",
    "expo-constants": "^14.0.2",
    "expo-keep-awake": "^11.0.1",
    "expo-linear-gradient": "^12.1.2",
    "expo-linking": "^3.2.3",
    "expo-local-authentication": "^13.0.2",
    "expo-location": "^15.0.1",
    "expo-network": "^5.0.0",
    "expo-sensors": "^12.0.1",
    "expo-store-review": "^6.0.0",
    "expo-task-manager": "^11.0.1",
    "faker": "^5.5.3",
    "fs": "0.0.1-security",
    "geolocation-utils": "^1.2.5",
    "libphonenumber-js": "^1.9.25",
    "lodash": "^4.17.21",
    "lottie-ios": "3.4.1",
    "lottie-react-native": "5.1.3",
    "moment": "^2.29.1",
    "npm": "^7.18.1",
    "npm-license-crawler": "^0.2.1",
    "patch-package": "^6.4.7",
    "path": "^0.12.7",
    "pretty-bytes": "^5.6.0",
    "react": "^18.2.0",
    "react-mixin": "^5.0.0",
    "react-native": "^0.70.6",
    "react-native-android-open-settings": "^1.3.0",
    "react-native-animatable": "^1.3.3",
    "react-native-background-timer": "^2.4.1",
    "react-native-contacts": "^7.0.4",
    "react-native-date-picker": "^4.2.5",
    "react-native-device-info": "^10.3.0",
    "react-native-fbsdk-next": "^10.0.0",
    "react-native-flipper": "0.163.0",
    "react-native-geocoding": "^0.5.0",
    "react-native-geolocation-service": "^5.3.0-beta.1",
    "react-native-gesture-handler": "^2.8.0",
    "react-native-get-random-values": "^1.8.0",
    "react-native-google-mobile-ads": "^9.1.1",
    "react-native-google-places-autocomplete": "^2.5.1",
    "react-native-gradle-plugin": "^0.70.0",
    "react-native-iap": "^12.7.2",
    "react-native-image-crop-picker": "^0.38.0",
    "react-native-in-app-review": "^4.3.1",
    "react-native-in-app-utils": "^6.1.0",
    "react-native-keyboard-aware-scroll-view": "^0.9.5",
    "react-native-localize": "^2.2.2",
    "react-native-maps": "^1.3.2",
    "react-native-notification-sounds": "^0.5.5",
    "react-native-onesignal": "^4.5.1",
    "react-native-permissions": "^3.6.0",
    "react-native-pose": "^0.9.1",
    "react-native-push-notification": "^8.1.1",
    "react-native-render-html": "^6.3.4",
    "react-native-ringer-mode": "^2.0.0",
    "react-native-safe-area-context": "^4.3.1",
    "react-native-screens": "^3.15.0",
    "react-native-splash-screen": "^3.3.0",
    "react-native-svg": "^13.4.0",
    "react-native-system-navigation-bar": "^1.0.5",
    "react-native-system-setting": "^1.7.6",
    "react-native-vector-icons": "^9.2.0",
    "react-redux": "^8.0.2",
    "react-timer-hook": "^3.0.5",
    "react-timer-mixin": "^0.13.4",
    "react-use": "^17.4.0",
    "redux": "^4.2.0",
    "redux-flipper": "^2.0.2",
    "redux-middleware-flipper": "^1.0.9",
    "redux-sentry-middleware": "^0.2.2",
    "redux-thunk": "^2.4.1",
    "rn-async-storage-flipper": "^0.0.10",
    "rn-emoji-keyboard": "^1.0.0",
    "rn-sliding-up-panel": "^2.4.6",
    "url-parse": "^1.5.10",
    "uuid": "^8.3.2",
    "validator": "^13.7.0"
  },
Christofon commented 1 year ago

Another workaround to solve this issue is to wrap your entry file in GestureHandlerRootView from react-native-gesture-handler and use Touchables from react-native-gesture-handler. This works because Touchables in react-native-gesture-handler do not use JS Responder system. Docs

This works for me as well and I will keep it like that until fixed.

One interesting thing I noticed was when only having the GestureHandlerRootView and a Touchable/Pressable in the App component, everything works flawlessly. As soon as react-navigation get's added, it stops working again.

IsuruSathyajith commented 1 year ago

Another workaround to solve this issue is to wrap your entry file in GestureHandlerRootView from react-native-gesture-handler and use Touchables from react-native-gesture-handler. This works because Touchables in react-native-gesture-handler do not use JS Responder system. Docs

This works for me as well and I will keep it like that until fixed.

One interesting thing I noticed was when only having the GestureHandlerRootView and a Button in the App component, everything works flawlessly. As soon as react-navigation get's added, it stops working again.

I tried creating a release build for Android without doing any workarounds we discussed and on the release build, all touch events worked fine, even on the same device I was trying before. Can you guys also try a release build and see what happens?

Christofon commented 1 year ago

Another workaround to solve this issue is to wrap your entry file in GestureHandlerRootView from react-native-gesture-handler and use Touchables from react-native-gesture-handler. This works because Touchables in react-native-gesture-handler do not use JS Responder system. Docs

This works for me as well and I will keep it like that until fixed. One interesting thing I noticed was when only having the GestureHandlerRootView and a Button in the App component, everything works flawlessly. As soon as react-navigation get's added, it stops working again.

I tried creating a release build for Android without doing any workarounds we discussed and on the release build, all touch events worked fine, even on the same device I was trying before. Can you guys also try a release build and see what happens?

Same behaviour in release build in my case. Already tried that. This also seems related to the Android version, does not happen on all our test devices.

IsuruSathyajith commented 1 year ago

Same behaviour in release build in my case. Already tried that. This also seems related to the Android version, does not happen on all our test devices.

Yes, I mostly had it on Android 13 devices; so I created this issue for the React Navigation library back then -> https://github.com/react-navigation/react-navigation/issues/11619

souza-dev commented 1 year ago

My company is willing to put a bounty of $1,000 on fixing this and getting it merged. If anyone else would like to add to the bounty, please chime in.

The reason this needs to be top priority is because concurrent react has been out for a long time, yet -- in practice -- not in the react-native world, as this issue makes Android useless, given all workarounds are unacceptable for pro apps.

For additional information, we currently have an app in both app stores, and I implemented an onPressIn hack + a timeout after scrolling so events aren't triggered while scrolling, and it's not satisfactory. The onPress prop of Pressable really needs to operate correctly for the new architecture to be ready for prime time.

All I had to do was disable the fabric in gradle.

rupeshkk-iprogrammer commented 1 year ago

any update on the touchable components?

Roshett commented 1 year ago

I encountered with the same bug

sagarjeu commented 1 year ago

Any update @satya164

javache commented 1 year ago

We expect some of this to be improved by https://github.com/facebook/react-native/commit/03f70bf995379f08a77abcf96bb0e31ff75ca8c3 which will ship in 0.73.

Crhaj commented 1 year ago

Thank you @javache, would it be possible to consider this to be also released as a patch for 0.72?

Siti-Shaufi commented 1 year ago

Thank you @javache, would it be possible to consider this to be also released as a patch for 0.72?

Currently on react-native 0.72.6 and react 18.2.0 with expo. All with latest dependencies. Still same issue. :(

ravindraguptacapgemini commented 1 year ago

I am also facing the same issue, specially on Android devices. Clicks do not work randomly but the scroll works fine at the same moment. Not sure why React Native/Meta developers are not fixing it, as this is very prominent issue. @cortinico

ravindraguptacapgemini commented 1 year ago

We expect some of this to be improved by 03f70bf which will ship in 0.73.

@javache I tried to patch this, but it did not work.

ryanstout commented 1 year ago

Same issue, our app is only for Android. Works in the emulator. Tried the latest RN and a few before. Thanks

aatiqDev1443 commented 1 year ago

Not working mostly for below android 11.

HadiModarres commented 12 months ago

Same issue with Android and new architecture enabled. I wonder how Meta works around these issues internally as they've been using the new architecture successfully in Facebook app for years. I assume they have their own alternative navigation library instead of react-navigation? Would be great if they could share their expertise, as adopting new architecture seems unattainable for the rest of us.

skinsapp commented 11 months ago

Is this working finally with RN 73? This is so important that Android with the new architecture is useless without this. Very sad.

It seems that at this point this would be a low enough hanging fruit providing enormous value that it is finally worth prioritizing.

faceyspacey commented 11 months ago

Looking forward to being able to use Android with the new architecture finally. Waiting on this too.

Wahsner commented 11 months ago

Still appear to be having this issue in 0.73.X on Android where the onPress isnt being triggered on, in this instance, the RN

mtjkln commented 11 months ago

@Wahsner

Yeah, exact case when it stops working when you turn on new arch.

Its very frustrating, that it still exists.

christophliftoff commented 11 months ago

Also experiencing this problem. It seems to be related to react-navigation, as all the reported instances from our users occur when the user attempts to navigate to a new screen. For example, user taps on the "back" button, no navigation occurs, but the back button's opacity changes, indicating that the button is partly responding to the touch.

As other's have reported on this GH issue, other components continue to work fine (such as scrollviews, etc). TouchableOpacity components stop working until the app is force closed and re-opened.

cortinico commented 11 months ago

Do we have a repro of any sort?

cipolleschi commented 11 months ago

Hi everyone, we might have landed a fix in main for this and we might be able to verify the fix using a nightly version.

Has any of you a repro that we can use to see if it is fixed? Pinging some of the recently active people: @christophliftoff, @mtjkln, @Wahsner, @faceyspacey, @the-skins-app?

joemun commented 10 months ago

Hi everyone, we might have landed a fix in main for this and we might be able to verify the fix using a nightly version.

@cipolleschi Mind sharing the relevant commits? We can try to test as well, thanks!

Siti-Shaufi commented 10 months ago

Hi everyone, we might have landed a fix in main for this and we might be able to verify the fix using a nightly version.

Has any of you a repro that we can use to see if it is fixed? Pinging some of the recently active people: @christophliftoff, @mtjkln, @Wahsner, @faceyspacey, @the-skins-app?

Can we know the solution, currently in 72.6 with the newArchitecture disabled and have react-navigation also have the same issue.

mtjkln commented 10 months ago

@Siti-Shaufi

The issue happens when new architecture is enabled. Apart from this I have never come across this issue.

Siti-Shaufi commented 10 months ago

@Siti-Shaufi

The issue happens when new architecture is enabled. Apart from this I have never come across this issue.

Alright, I will check again. As my issue happen when the new architecture is disabled. Thanks!

mtjkln commented 10 months ago

@cipolleschi

The issue happens when new architecture is enabled. Apart from this I have never come across this issue.

Crhaj commented 10 months ago

@cipolleschi

The issue happens when new architecture is enabled. Apart from this I have never come across this issue.

We (and other people here) have experienced the issue on the old architecture as well, so I don't think the architecture is the determining factor.

cipolleschi commented 10 months ago

@joemun sure! These are the relevant commits:

hollanderbart commented 10 months ago

In which next version will these commits be included?

oliverphardman commented 10 months ago

Following as I am also experiencing this, even on Android 5, on old architecture. Reproducing is very difficult because often a re-render will fix the problem. ScrollViews still function normally, but Pressables don't respond at all. No feedback, not even an Android ripple.

cipolleschi commented 10 months ago

@hollanderbart for the time being, we are considering these for 0.74.

If this is something that is crippling your 0.73 app, please add them as a pick request in the discussion

Crhaj commented 10 months ago

Requested in the discussion thread. Please upvote if you want it cherry picked to 0.73

hollanderbart commented 10 months ago

Did anyone test if the relevant commit(s) actually resolved the issue? @joemun @Siti-Shaufi

Bowlerr commented 10 months ago

Having the same issue with react-native-gesture-handler on Android, are there any solutions to this?

cipolleschi commented 10 months ago

@Crhaj, @joemun @Siti-Shaufi @Bowlerr can you try if the commits I linked above fixes the issues for you?

Or can you provide a reproducer so I can try that out myself? (Pro tip: you can use 0.73 to repro the failure and then use a nightly to verify that it is solved)

Thank you so much! 🙏

Crhaj commented 10 months ago

@Crhaj, @joemun @Siti-Shaufi @Bowlerr can you try if the commits I linked above fixes the issues for you?

Or can you provide a reproducer so I can try that out myself? (Pro tip: you can use 0.73 to repro the failure and then use a nightly to verify that it is solved)

Thank you so much! 🙏

@cipolleschi unfortunately, in our case, we couldn't reliably reproduce the issue and it seemed to happen randomly.

Bowlerr commented 10 months ago

Same with @Crhaj, We couldn't reproduce the issue reliably.

joemun commented 10 months ago

can you try if the commits I linked above fixes the issues for you?

@cipolleschi Sorry for the delay. I'm sad to say that those 2 commits (cherry-picked to our 72.3 branch) don't fix the issue for us.

skinsapp commented 10 months ago

The issue only occurs when useNativeDriver is set:

https://github.com/facebook/react-native/issues/36504#issuecomment-1586137079

So if various automated tests are neglecting to set that to true, then you won't see the issue. @sammy-SC at Facebook seems to have figured that out as he just re-opened the above related issue.

cipolleschi commented 10 months ago

@joemun, thanks for letting us know.

We have this investigation marked as high priority, so we hopefully would be able to make progress on this as fast as we can.

To help us out, we would greatly appreciate a reproducer starting from this repo. I understand that the issue does not reproduce consistently, but if you can set up something and tell us how and how much we need to interact with the repro to get the issue happening, this will help us a lot.

Thank you all for the cooperation! 🙏

rupeshkk-iprogrammer commented 10 months ago

The issue happens when new architecture is enabled and also in Reac-Native 73 new arch = true. Apart from this I have never come across this issue.

kchh90 commented 10 months ago

I can confirm we're experiencing this issue as well on react-native 73.2 when new architecture is enabled for Android. The issue we face is with onPress only working intermittently on physical android devices. The issue does not occur on android emulator devices.

@cipolleschi I have been able to consistently reproduce this issue with the following repro by clicking the "CLICK ME" button multiple times and not seeing each click generate the expected timestamp output in the console.

For me this issue only present itself within a react-navigation screen, when a button is placed outside the react-navigation screen there is no issue with its onPress behaviour.

cortinico commented 10 months ago

@cipolleschi I have been able to consistently reproduce this issue with the following repro by clicking the "CLICK ME" button multiple times and not seeing each click generate the expected timestamp output in the console.

@kchh90 thanks for the reproducer. However, it seems to work fine on my end. See the attached video:

https://github.com/facebook/react-native/assets/3001957/3af1c69e-c14b-4a6d-a9a0-6a47cb15cf20

Christofon commented 10 months ago

@cipolleschi I have been able to consistently reproduce this issue with the following repro by clicking the "CLICK ME" button multiple times and not seeing each click generate the expected timestamp output in the console.

@kchh90 thanks for the reproducer. However, it seems to work fine on my end. See the attached video:

Screen.Recording.2024-01-26.at.09.54.20.mov

This is only happening on physical devices, at least for me.

kchh90 commented 10 months ago

@cipolleschi I have been able to consistently reproduce this issue with the following repro by clicking the "CLICK ME" button multiple times and not seeing each click generate the expected timestamp output in the console.

@kchh90 thanks for the reproducer. However, it seems to work fine on my end. See the attached video:

Screen.Recording.2024-01-26.at.09.54.20.mov

Yes sorry, I should have been more clear that the issue is only reproducible on physical android devices but not on android emulators.

kchh90 commented 10 months ago

Here's a short recording of the issue occurring on a physical android device. I added an alert to the button's onPress behaviour to better showcase the issue directly on the device: https://github.com/facebook/react-native/assets/1700361/21a28388-df28-492b-bfc0-9d3150866250

I'm running it on Android 14 Pixel 7 in this example, but have tried it on a few other physical android devices and see the same issue, so doesn't seem to be device specific.

cortinico commented 10 months ago

Hey @kchh90 thanks for your reproducer, after furhter investigation, we were able to reproduce (I'd like to stress once more how having a simple/small reproducer was crucial here! Thank you again).

  1. The issue happens on either emulator or physical device. The issue happens if you touch, move the finger, and release it.
  2. The issue seems to be related to react-native-screens. It won't happen on a vanilla native app (cc @WoLewicki)

We'll follow up with next steps once we have a solution for this

kchh90 commented 10 months ago

@cortinico Awesome, thank you very much for the effort in looking into this issue!

Through further testing, I've discovered that disabling the header for a given screen also appears to workaround this issue.

For example, by adding the following options to the screen in the repro as such:

<Stack.Screen
  name="Test"
  component={TestScreen}
  options={{
    headerShown: false,
  }}
/>