From 89ef5bd6f9064298dfe55b0b18be4a770ee0872c Mon Sep 17 00:00:00 2001 From: Xin Chen Date: Tue, 14 Feb 2023 22:32:55 -0800 Subject: [PATCH] Add TraceUpdateOverlay to RN AppContainer Summary: This diff adds `TraceUpdateOverlay` native component to RN `AppContainer.js`. This will enable the overlay when the build is in DEV environment and the DevTools global hook exists. It also closed gap between the JS dev mode and native dev support flag, so that the native component will be available when used by JS. ## Update (2/13/2023) Instead of the original approach where I put a default value to the devsupport manager flag, I did ui manager check from JS and make sure the native component exists before using it. This is cleaner. ## Problem Since the `AppContainer` is being used by all RN apps, we need to make sure the native component is registered in UI Manager of the RN app when it's used. Currently, the native component lives in the `DebugCorePackage.java`, which is added to the RN app [when the `DevSupportManager` is used](https://fburl.com/code/muqmqbsa). However, there's no way to tell if an app is using dev support manager in JS, hence there are gaps when the JS code uses `TraceUpdateOverlay`, vs when the native code registered the native component. This issue caused test error in [ReactNativePerfTest](https://fburl.com/testinfra/j24wzh46) from the [previous diff](https://fburl.com/diff/bv9ckhm7), and it actually prevents Flipper from running this properly as shown in this video: https://pxl.cl/2sqKf The errors shown in Flipper indicates the RN surface from the plugin is also missing `TraceUpdateOverlay` in its UI Manager: {F869168865} ## Solution To fix this issue, we should find a way to expose if the app is using dev support manager in JS. Or we should set to use DevSupportManager whenever it's a dev build as claimed in JS. I will try to find some way to achieve either one of this. I am open to suggestions here for where I should add the native component to. Given that it's used in the AppContainer, and any app could be built in development mode, I don't want to make people to manually add this native component themselves. ## Alternatives There are some other approaches that could mitigate the issue, but less ideal: For the test issue 1) Add `setUseDeveloperSupport(true)` to [ReactNativeTestRule.java](https://fburl.com/code/7jaoamdp). That will make the related test pass by using the DevSupportPackages, which has the native component. However, it only fixes tests using that class. 2) Override the package for [ReactNativeTestRule.java](https://fburl.com/code/b4em32fa), or `addPackage` with more packages including the native component. Again this only fixes this test. 3) Add the native component to the [`MainReactPackage`](https://fburl.com/code/nlayho86), which is what I did here in this diff. This would fix more cases as this package is [recommended to be used](https://fburl.com/code/53eweuoh) for all RN app. However, it may not fix all the cases if the RN app didn't manually use it. 4) Add the native component in the [`CoreModulesPackage`](https://fburl.com/code/lfeklztl), which will make all RN apps work, but at the cost of increase package size when this feature is not needed. Or, we could argue that we want to have highlights on trace updates for production build as well? Changelog: [Internal] - Enable TraceUpdateOverlay to RN AppContainer Reviewed By: rubennorte Differential Revision: D43180893 fbshipit-source-id: a1530cc6e2a9d8c905bdfe5d622d85c4712266f8 --- .../TraceUpdateOverlay/TraceUpdateOverlay.js | 10 +++++++++- Libraries/ReactNative/AppContainer.js | 8 +++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js b/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js index 6e5914fd25b26f..e0318fac9c4a15 100644 --- a/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js +++ b/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js @@ -10,6 +10,7 @@ import type {Overlay} from './TraceUpdateOverlayNativeComponent'; +import UIManager from '../../ReactNative/UIManager'; import processColor from '../../StyleSheet/processColor'; import StyleSheet from '../../StyleSheet/StyleSheet'; import View from '../View/View'; @@ -53,6 +54,8 @@ type ReactDevToolsGlobalHook = { const {useEffect, useRef, useState} = React; const hook: ReactDevToolsGlobalHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__; +const isNativeComponentReady = + UIManager.hasViewManagerConfig('TraceUpdateOverlay'); let devToolsAgent: ?Agent; export default function TraceUpdateOverlay(): React.Node { @@ -60,6 +63,10 @@ export default function TraceUpdateOverlay(): React.Node { // This effect is designed to be explictly shown here to avoid re-subscribe from the same // overlay component. useEffect(() => { + if (!isNativeComponentReady) { + return; + } + function attachToDevtools(agent: Agent) { devToolsAgent = agent; agent.addListener('drawTraceUpdates', onAgentDrawTraceUpdates); @@ -141,7 +148,8 @@ export default function TraceUpdateOverlay(): React.Node { useRef>(null); return ( - !overlayDisabled && ( + !overlayDisabled && + isNativeComponentReady && ( { state: State = { inspector: null, devtoolsOverlay: null, + traceUpdateOverlay: null, mainKey: 1, hasError: false, }; @@ -75,7 +77,10 @@ class AppContainer extends React.Component { const devtoolsOverlay = ( ); - this.setState({devtoolsOverlay}); + const TraceUpdateOverlay = + require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default; + const traceUpdateOverlay = ; + this.setState({devtoolsOverlay, traceUpdateOverlay}); } } } @@ -127,6 +132,7 @@ class AppContainer extends React.Component { {!this.state.hasError && innerView} + {this.state.traceUpdateOverlay} {this.state.devtoolsOverlay} {this.state.inspector} {logBox}