react-native-tvos: Apple TV: menu key gesture recognizer not working on Modal or on native stack navigator

Description

This issue appeared while using the createNativeStackNavigator from react-navigation and react-native-screens.

createNativeStackNavigator creates a new UINavigationController and UIViewController which seems to handle by default the “menu” button to go back to the previous screen on the navigation stack.

The current implementation of RCTTVRemoteHandler only applies to the RCTRootView. Since the root view is the first view in the view hierarchy, it is gonna be the last one to receive a menuPressed: event after every potential propagation. So the UINavigationController created by react-native-screens will always override a menuPressed: event when the app is inside a stack screen.

We fixed it by initing a RCTTVRemoteHandler for every RCTTVView: https://github.com/SRGSSR/react-native-tvos/pull/2. However it seems overkill to do it for every single view and definitely not the cleanest way.

We didn’t find a cleaner/easier way to do it since the issue is kinda shared between the remote event handling implementation here and how react-native-screens works.

Version

0.68.2-6

Output of npx react-native info

System:

  • OS: macOS 12.3.1
  • CPU: (8) arm64 Apple M1
  • Memory: 125.94 MB / 16.00 GB
  • Shell: 5.8 - /bin/zsh

Binaries:

  • Node: 14.18.2 - ~/.nvm/versions/node/v14.18.2/bin/node
  • Yarn: 1.22.17 - /opt/homebrew/bin/yarn

CocoaPods: 1.11.3 - /opt/homebrew/bin/pod

iOS SDK:

  • Platforms: DriverKit 21.4, iOS 15.5, macOS 12.3, tvOS 15.4, watchOS 8.5

IDEs:

  • Xcode: 13.4.1/13F100 - /usr/bin/xcodebuild

Steps to reproduce

  1. add react-navigation and react-native-screens to your project
  2. create a stack navigator using createNativeStackNavigator
  3. try to get the menu event using BackHandler inside a stack screen

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

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 23

Most upvoted comments

It seems like when we first try to set useTVPreferredFocus to true on mount, the react-native-screens’ RNSScreenView/RNSScreen is not yet in the window?

2022-10-20 11:42:04.057928+0200 ReactNavigationTvOSApp-tvOS[95096:21715089] rootview is: RCTTVView
2022-10-20 11:42:04.058319+0200 ReactNavigationTvOSApp-tvOS[95096:21715089] rootview is: RCTTVView
2022-10-20 11:42:04.058513+0200 ReactNavigationTvOSApp-tvOS[95096:21715089] rootview is: RCTTVView
2022-10-20 11:42:04.058760+0200 ReactNavigationTvOSApp-tvOS[95096:21715089] rootview is: RNSScreenView
2022-10-20 11:42:04.058963+0200 ReactNavigationTvOSApp-tvOS[95096:21715089] rootview is: (null)

If we call [self rootView] from didMoveToWindow, it successfully finds the RCTRootContentView.

Wow the modal example is interesting indeed. It seems that tvOS has changed the way they do modal presentations – the menu key goes to the modal view controller’s view, bypassing any recognizers set on RCTModalHostView.

I’ll do some work to fix that, and then take a look at the react-native-screens issue.

For completeness we also tried to add a remote handler only to RNSScreenView and that works as well. But this creates an undesirable dependency between react-native-screens and react-native-tvos