Skip to content

Commit

Permalink
fix[AppContainer]: mount react devtools overlay only when devtools ar…
Browse files Browse the repository at this point in the history
…e 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: fa9c34137c2711e74bba5b92fa7aafa4173e6bdd
  • Loading branch information
hoxyq authored and facebook-github-bot committed Aug 4, 2023
1 parent 5eb0685 commit 3901688
Showing 1 changed file with 32 additions and 9 deletions.
41 changes: 32 additions & 9 deletions packages/react-native/Libraries/ReactNative/AppContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {type EventSubscription} from '../vendor/emitter/EventEmitter';
import {RootTagContext, createRootTag} from './RootTag';
import * as React from 'react';

const reactDevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;

type Props = $ReadOnly<{|
children?: React.Node,
fabric?: boolean,
Expand Down Expand Up @@ -45,9 +47,21 @@ class AppContainer extends React.Component<Props, State> {
};
_mainRef: ?React.ElementRef<typeof View>;
_subscription: ?EventSubscription = null;
_reactDevToolsAgentListener: ?() => void = null;

static getDerivedStateFromError: any = undefined;

mountReactDevToolsOverlays(): void {
const DevtoolsOverlay = require('../Inspector/DevtoolsOverlay').default;
const devtoolsOverlay = <DevtoolsOverlay inspectedView={this._mainRef} />;

const TraceUpdateOverlay =
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
const traceUpdateOverlay = <TraceUpdateOverlay />;

this.setState({devtoolsOverlay, traceUpdateOverlay});
}

componentDidMount(): void {
if (__DEV__) {
if (!this.props.internal_excludeInspector) {
Expand All @@ -69,16 +83,21 @@ class AppContainer extends React.Component<Props, State> {
this.setState({inspector});
},
);
if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__ != null) {
const DevtoolsOverlay =
require('../Inspector/DevtoolsOverlay').default;
const devtoolsOverlay = (
<DevtoolsOverlay inspectedView={this._mainRef} />

if (reactDevToolsHook != null) {
if (reactDevToolsHook.reactDevtoolsAgent) {
// In case if this is not the first AppContainer rendered and React DevTools are already attached
this.mountReactDevToolsOverlays();
return;
}

this._reactDevToolsAgentListener = () =>
this.mountReactDevToolsOverlays();

reactDevToolsHook.on(
'react-devtools',
this._reactDevToolsAgentListener,
);
const TraceUpdateOverlay =
require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default;
const traceUpdateOverlay = <TraceUpdateOverlay />;
this.setState({devtoolsOverlay, traceUpdateOverlay});
}
}
}
Expand All @@ -88,6 +107,10 @@ class AppContainer extends React.Component<Props, State> {
if (this._subscription != null) {
this._subscription.remove();
}

if (reactDevToolsHook != null && this._reactDevToolsAgentListener != null) {
reactDevToolsHook.off('react-devtools', this._reactDevToolsAgentListener);
}
}

render(): React.Node {
Expand Down

0 comments on commit 3901688

Please sign in to comment.