Skip to content

Commit ea3efa8

Browse files
committed
fix[AppContainer]: mount react devtools overlay only when devtools are connected (#38727)
Summary: Pull Request resolved: #38727 ## Changelog: [General][Fix] - Do not render React DevTools overlays unless they are connected Fixes #38024. Reproducible example: https://github.com/rasaha91/rn-bottomsheet. - This is a temporary workaround to resolve described problem for DEV bundles without attached React DevTools. - Still, such problem will be present for DEV bundles with attached React DevTools, but this should be only for brownfield apps with a shrinked React Native window. Checking that DevTools hook is present is not enough to determine whether the DevTools are connected. These changes fix it. Short description of what's going on there: 1. When React Native root window is rendered inside some native view, which takes only portion of the screen (like the native bottom sheet in the reproducible example), DevtoolsOverlay / InspectorOverlay takes up space based on application window dimension, this results into resizing the hosting window on the native side. https://pxl.cl/357r3 2. Right way to fix this would be removing the usage of application window sizes, so that DevtoolsOverlay / InspectorOverlay will be allowed only to take React Native's window. 3. Unfortunately, just removing setting is not enough, we should also have at least 1 of 2 things: - `collapsable` prop should be set to `true` => View will be flattened - Remove [`flex: 1` style on both root and inner Views](https://github.com/facebook/react-native/blob/b28e3c16ed7cbc8b3ed3f26d91c58acb4bb28879/packages/react-native/Libraries/ReactNative/AppContainer.js#L145-L147), but this is breaking how LogBox works now. | {F1062478964} | {F1062492367} Reviewed By: NickGerleman Differential Revision: D47954883 fbshipit-source-id: d45d8cb82daa8dc9de58f54c137815b3a7abd5db
1 parent 79c4ec1 commit ea3efa8

File tree

1 file changed

+32
-9
lines changed

1 file changed

+32
-9
lines changed

packages/react-native/Libraries/ReactNative/AppContainer.js

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import {type EventSubscription} from '../vendor/emitter/EventEmitter';
1717
import {RootTagContext, createRootTag} from './RootTag';
1818
import * as React from 'react';
1919

20+
const reactDevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
21+
2022
type Props = $ReadOnly<{|
2123
children?: React.Node,
2224
fabric?: boolean,
@@ -47,9 +49,21 @@ class AppContainer extends React.Component<Props, State> {
4749
};
4850
_mainRef: ?React.ElementRef<typeof View>;
4951
_subscription: ?EventSubscription = null;
52+
_reactDevToolsAgentListener: ?() => void = null;
5053

5154
static getDerivedStateFromError: any = undefined;
5255

56+
mountReactDevToolsOverlays(): void {
57+
const DevtoolsOverlay = require('../Inspector/DevtoolsOverlay').default;
58+
const devtoolsOverlay = <DevtoolsOverlay inspectedView={this._mainRef} />;
59+
60+
const TraceUpdateOverlay =
61+
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
62+
const traceUpdateOverlay = <TraceUpdateOverlay />;
63+
64+
this.setState({devtoolsOverlay, traceUpdateOverlay});
65+
}
66+
5367
componentDidMount(): void {
5468
if (__DEV__) {
5569
if (!this.props.internal_excludeInspector) {
@@ -71,16 +85,21 @@ class AppContainer extends React.Component<Props, State> {
7185
this.setState({inspector});
7286
},
7387
);
74-
if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__ != null) {
75-
const DevtoolsOverlay =
76-
require('../Inspector/DevtoolsOverlay').default;
77-
const devtoolsOverlay = (
78-
<DevtoolsOverlay inspectedView={this._mainRef} />
88+
89+
if (reactDevToolsHook != null) {
90+
if (reactDevToolsHook.reactDevtoolsAgent) {
91+
// In case if this is not the first AppContainer rendered and React DevTools are already attached
92+
this.mountReactDevToolsOverlays();
93+
return;
94+
}
95+
96+
this._reactDevToolsAgentListener = () =>
97+
this.mountReactDevToolsOverlays();
98+
99+
reactDevToolsHook.on(
100+
'react-devtools',
101+
this._reactDevToolsAgentListener,
79102
);
80-
const TraceUpdateOverlay =
81-
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
82-
const traceUpdateOverlay = <TraceUpdateOverlay />;
83-
this.setState({devtoolsOverlay, traceUpdateOverlay});
84103
}
85104
}
86105
}
@@ -90,6 +109,10 @@ class AppContainer extends React.Component<Props, State> {
90109
if (this._subscription != null) {
91110
this._subscription.remove();
92111
}
112+
113+
if (reactDevToolsHook != null && this._reactDevToolsAgentListener != null) {
114+
reactDevToolsHook.off('react-devtools', this._reactDevToolsAgentListener);
115+
}
93116
}
94117

95118
render(): React.Node {

0 commit comments

Comments
 (0)