Skip to content

Commit eb9ecc2

Browse files
hoxyqfacebook-github-bot
authored andcommitted
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 e22d1a1 commit eb9ecc2

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,
@@ -45,9 +47,21 @@ class AppContainer extends React.Component<Props, State> {
4547
};
4648
_mainRef: ?React.ElementRef<typeof View>;
4749
_subscription: ?EventSubscription = null;
50+
_reactDevToolsAgentListener: ?() => void = null;
4851

4952
static getDerivedStateFromError: any = undefined;
5053

54+
mountReactDevToolsOverlays(): void {
55+
const DevtoolsOverlay = require('../Inspector/DevtoolsOverlay').default;
56+
const devtoolsOverlay = <DevtoolsOverlay inspectedView={this._mainRef} />;
57+
58+
const TraceUpdateOverlay =
59+
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
60+
const traceUpdateOverlay = <TraceUpdateOverlay />;
61+
62+
this.setState({devtoolsOverlay, traceUpdateOverlay});
63+
}
64+
5165
componentDidMount(): void {
5266
if (__DEV__) {
5367
if (!this.props.internal_excludeInspector) {
@@ -69,16 +83,21 @@ class AppContainer extends React.Component<Props, State> {
6983
this.setState({inspector});
7084
},
7185
);
72-
if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__ != null) {
73-
const DevtoolsOverlay =
74-
require('../Inspector/DevtoolsOverlay').default;
75-
const devtoolsOverlay = (
76-
<DevtoolsOverlay inspectedView={this._mainRef} />
86+
87+
if (reactDevToolsHook != null) {
88+
if (reactDevToolsHook.reactDevtoolsAgent) {
89+
// In case if this is not the first AppContainer rendered and React DevTools are already attached
90+
this.mountReactDevToolsOverlays();
91+
return;
92+
}
93+
94+
this._reactDevToolsAgentListener = () =>
95+
this.mountReactDevToolsOverlays();
96+
97+
reactDevToolsHook.on(
98+
'react-devtools',
99+
this._reactDevToolsAgentListener,
77100
);
78-
const TraceUpdateOverlay =
79-
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
80-
const traceUpdateOverlay = <TraceUpdateOverlay />;
81-
this.setState({devtoolsOverlay, traceUpdateOverlay});
82101
}
83102
}
84103
}
@@ -88,6 +107,10 @@ class AppContainer extends React.Component<Props, State> {
88107
if (this._subscription != null) {
89108
this._subscription.remove();
90109
}
110+
111+
if (reactDevToolsHook != null && this._reactDevToolsAgentListener != null) {
112+
reactDevToolsHook.off('react-devtools', this._reactDevToolsAgentListener);
113+
}
91114
}
92115

93116
render(): React.Node {

0 commit comments

Comments
 (0)