Skip to content

Commit

Permalink
Add TraceUpdateOverlay to RN AppContainer
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Xin Chen authored and facebook-github-bot committed Feb 15, 2023
1 parent 11570e7 commit 89ef5bd
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
10 changes: 9 additions & 1 deletion Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js
Expand Up @@ -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';
Expand Down Expand Up @@ -53,13 +54,19 @@ 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 {
const [overlayDisabled, setOverlayDisabled] = useState(false);
// 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);
Expand Down Expand Up @@ -141,7 +148,8 @@ export default function TraceUpdateOverlay(): React.Node {
useRef<?React.ElementRef<typeof TraceUpdateOverlayNativeComponent>>(null);

return (
!overlayDisabled && (
!overlayDisabled &&
isNativeComponentReady && (
<View pointerEvents="none" style={styles.overlay}>
<TraceUpdateOverlayNativeComponent
ref={nativeComponentRef}
Expand Down
8 changes: 7 additions & 1 deletion Libraries/ReactNative/AppContainer.js
Expand Up @@ -32,6 +32,7 @@ type Props = $ReadOnly<{|
type State = {|
inspector: ?React.Node,
devtoolsOverlay: ?React.Node,
traceUpdateOverlay: ?React.Node,
mainKey: number,
hasError: boolean,
|};
Expand All @@ -40,6 +41,7 @@ class AppContainer extends React.Component<Props, State> {
state: State = {
inspector: null,
devtoolsOverlay: null,
traceUpdateOverlay: null,
mainKey: 1,
hasError: false,
};
Expand Down Expand Up @@ -75,7 +77,10 @@ class AppContainer extends React.Component<Props, State> {
const devtoolsOverlay = (
<DevtoolsOverlay inspectedView={this._mainRef} />
);
this.setState({devtoolsOverlay});
const TraceUpdateOverlay =
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
const traceUpdateOverlay = <TraceUpdateOverlay />;
this.setState({devtoolsOverlay, traceUpdateOverlay});
}
}
}
Expand Down Expand Up @@ -127,6 +132,7 @@ class AppContainer extends React.Component<Props, State> {
<RootTagContext.Provider value={createRootTag(this.props.rootTag)}>
<View style={styles.appContainer} pointerEvents="box-none">
{!this.state.hasError && innerView}
{this.state.traceUpdateOverlay}
{this.state.devtoolsOverlay}
{this.state.inspector}
{logBox}
Expand Down

0 comments on commit 89ef5bd

Please sign in to comment.