react-native
react-native copied to clipboard
[Android] Unrecoverable crash when calling setAccessibilityFocus on a component that is unmounting
Description
When using the AccessibilityInfo.setAccessibilityFocus
operator on Android, your app can fatally crash. This can happen while a component is in the process of being unmounted, and fails with the error: com.facebook.react.bridge.JSApplicationIllegalArgumentException: Could not find view with tag N
.
We encountered this bug because we inserted an artificial delay on setting accessibility focus to small alert bars that appear when something goes wrong (i.e. the user forgot to fill a form input or a network request has failed). However, the user has the option to close that alert before it has finished animating. The expected behavior is for findNodeHandle
to trigger an exception on the JS side but instead it yields a valid React tag which is then fed onto the native side via setAccessibilityFocus
. Before that event is processed in the UIViewOperationQueue
, the view is removed. Upon executing that event, the exception from above is raised and the user's app crashes.
Version
0.61.0 (and up)
Output of npx react-native info
System:
OS: macOS 11.6
CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 732.75 MB / 16.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 14.17.4 - ~/.nvm/versions/node/v14.17.4/bin/node
Yarn: Not Found
npm: 6.14.14 - ~/.nvm/versions/node/v14.17.4/bin/npm
Watchman: 2021.10.04.00 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.10.1 - /Users/pabbondanzo/.gem/ruby/2.6.0/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 15.0, DriverKit 20.4, macOS 11.3, tvOS 15.0, watchOS 8.0
Android SDK: Not Found
IDEs:
Android Studio: 2020.3 AI-203.7717.56.2031.7935034
Xcode: 13.0/13A233 - /usr/bin/xcodebuild
Languages:
Java: 11.0.12 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: Not Found
react-native: 0.64.2 => 0.64.2
react-native-macos: Not Found
npmGlobalPackages:
*react-native*: Not Found
Steps to reproduce
This problem is unique to Android, but in effect the steps are:
- Just before a component is set to unmount (or, with a delayed timer) a reference to that component is held onto
- As the component is unmounting, call
findNodeHandle
with that component's ref to get the tag of that component, and feed that tag intoAccessibilityInfo.setAccessibilityFocus
- The app should quickly crash with the exception
JSApplicationIllegalArgumentException: Could not find view with tag N
The Expo snack below has an example application that will immediately crash when you press on the "Trigger Crash" button. The timer is there to signify that the app is in an unrecoverable state, and the "Reset" button should not be pressable
Snack, code example, screenshot, or link to a repository
https://snack.expo.dev/@abbondanzo/react-native-setaccessibilityfocus-crash
Linking out to a similar issue from a few years ago. The view in question in this issue is marked correctly as accessible, so it's not completely related, but similar findings of what causes the crash: https://github.com/facebook/react-native/issues/22807
It would be nice if we could catch the exception instead of crashing the app.
Closed by https://github.com/facebook/react-native/pull/37002