Skip to content

Commit 4fe2556

Browse files
committed
feat: expose installHook with settings argument from react-devtools-core/backend
1 parent 7a6d24b commit 4fe2556

File tree

2 files changed

+57
-23
lines changed

2 files changed

+57
-23
lines changed

packages/react-devtools-core/README.md

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,41 @@ If you are building a non-browser-based React renderer, you can use the backend
1414

1515
```js
1616
if (process.env.NODE_ENV !== 'production') {
17-
const { connectToDevTools } = require("react-devtools-core");
17+
const { initialize, connectToDevTools } = require("react-devtools-core");
1818

19+
initialize(settings);
1920
// Must be called before packages like react or react-native are imported
20-
connectToDevTools({
21-
...config
22-
});
21+
connectToDevTools({...config});
2322
}
2423
```
2524

2625
> **NOTE** that this API (`connectToDevTools`) must be (1) run in the same context as React and (2) must be called before React packages are imported (e.g. `react`, `react-dom`, `react-native`).
2726
27+
### `initialize` arguments
28+
| Argument | Description |
29+
|------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
30+
| `settings` | Optional. If not specified, or received as null, then default settings are going to be applied: appending component stacks to error messages and displaying inline errors and warnings.<br/>Can be plain object or a Promise that resolves with the plain object with [these boolean fields](https://github.com/facebook/react/blob/20cec76c44f77e74b3a85225fecab5a431cd986f/packages/react-devtools-shared/src/backend/types.js#L531-L536). If Promise rejects, the console will not be patched and some console features from React DevTools will not work. |
31+
2832
### `connectToDevTools` options
29-
| Prop | Default | Description |
30-
|---|---|---|
31-
| `host` | `"localhost"` | Socket connection to frontend should use this host. |
32-
| `isAppActive` | | (Optional) function that returns true/false, telling DevTools when it's ready to connect to React. |
33-
| `port` | `8097` | Socket connection to frontend should use this port. |
34-
| `resolveRNStyle` | | (Optional) function that accepts a key (number) and returns a style (object); used by React Native. |
35-
| `retryConnectionDelay` | `200` | Delay (ms) to wait between retrying a failed Websocket connection |
36-
| `useHttps` | `false` | Socket connection to frontend should use secure protocol (wss). |
37-
| `websocket` | | Custom `WebSocket` connection to frontend; overrides `host` and `port` settings. |
33+
| Prop | Default | Description |
34+
|------------------------|---------------|---------------------------------------------------------------------------------------------------------------------------|
35+
| `host` | `"localhost"` | Socket connection to frontend should use this host. |
36+
| `isAppActive` | | (Optional) function that returns true/false, telling DevTools when it's ready to connect to React. |
37+
| `port` | `8097` | Socket connection to frontend should use this port. |
38+
| `resolveRNStyle` | | (Optional) function that accepts a key (number) and returns a style (object); used by React Native. |
39+
| `retryConnectionDelay` | `200` | Delay (ms) to wait between retrying a failed Websocket connection |
40+
| `useHttps` | `false` | Socket connection to frontend should use secure protocol (wss). |
41+
| `websocket` | | Custom `WebSocket` connection to frontend; overrides `host` and `port` settings. |
42+
| `onSettingsUpdated` | | A callback that will be called when the user updates the settings in the UI. You can use it for persisting user settings. | |
3843

3944

4045
### `connectWithCustomMessagingProtocol` options
41-
| Prop | Description |
42-
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
43-
| `onSubscribe` | Function, which receives listener (function, with a single argument) as an argument. Called when backend subscribes to messages from the other end (frontend). |
44-
| `onUnsubscribe` | Function, which receives listener (function) as an argument. Called when backend unsubscribes to messages from the other end (frontend). |
45-
| `onMessage` | Function, which receives 2 arguments: event (string) and payload (any). Called when backend emits a message, which should be sent to the frontend. |
46+
| Prop | Description |
47+
|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
48+
| `onSubscribe` | Function, which receives listener (function, with a single argument) as an argument. Called when backend subscribes to messages from the other end (frontend). |
49+
| `onUnsubscribe` | Function, which receives listener (function) as an argument. Called when backend unsubscribes to messages from the other end (frontend). |
50+
| `onMessage` | Function, which receives 2 arguments: event (string) and payload (any). Called when backend emits a message, which should be sent to the frontend. |
51+
| `onSettingsUpdated` | A callback that will be called when the user updates the settings in the UI. You can use it for persisting user settings. |
4652

4753
Unlike `connectToDevTools`, `connectWithCustomMessagingProtocol` returns a callback, which can be used for unsubscribing the backend from the global DevTools hook.
4854

packages/react-devtools-core/src/backend.js

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ import type {
2020
ComponentFilter,
2121
Wall,
2222
} from 'react-devtools-shared/src/frontend/types';
23-
import type {DevToolsHook} from 'react-devtools-shared/src/backend/types';
23+
import type {
24+
DevToolsHook,
25+
DevToolsHookSettings,
26+
} from 'react-devtools-shared/src/backend/types';
2427
import type {ResolveNativeStyle} from 'react-devtools-shared/src/backend/NativeStyleEditor/setupNativeStyleEditor';
2528

2629
type ConnectOptions = {
@@ -32,12 +35,9 @@ type ConnectOptions = {
3235
retryConnectionDelay?: number,
3336
isAppActive?: () => boolean,
3437
websocket?: ?WebSocket,
38+
onSettingsUpdated?: (settings: DevToolsHookSettings) => void,
3539
};
3640

37-
installHook(window);
38-
39-
const hook: ?DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
40-
4141
let savedComponentFilters: Array<ComponentFilter> =
4242
getDefaultComponentFilters();
4343

@@ -52,11 +52,21 @@ function debug(methodName: string, ...args: Array<mixed>) {
5252
}
5353
}
5454

55+
export function initialize(
56+
maybeSettingsOrSettingsPromise?:
57+
| DevToolsHookSettings
58+
| Promise<DevToolsHookSettings>,
59+
) {
60+
installHook(window, maybeSettingsOrSettingsPromise);
61+
}
62+
5563
export function connectToDevTools(options: ?ConnectOptions) {
64+
const hook: ?DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
5665
if (hook == null) {
5766
// DevTools didn't get injected into this page (maybe b'c of the contentType).
5867
return;
5968
}
69+
6070
const {
6171
host = 'localhost',
6272
nativeStyleEditorValidAttributes,
@@ -66,6 +76,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
6676
resolveRNStyle = (null: $FlowFixMe),
6777
retryConnectionDelay = 2000,
6878
isAppActive = () => true,
79+
onSettingsUpdated,
6980
} = options || {};
7081

7182
const protocol = useHttps ? 'wss' : 'ws';
@@ -160,7 +171,14 @@ export function connectToDevTools(options: ?ConnectOptions) {
160171
// TODO (npm-packages) Warn if "isBackendStorageAPISupported"
161172
// $FlowFixMe[incompatible-call] found when upgrading Flow
162173
const agent = new Agent(bridge);
174+
if (onSettingsUpdated != null) {
175+
agent.addListener('updateHookSettings', onSettingsUpdated);
176+
}
163177
agent.addListener('shutdown', () => {
178+
if (onSettingsUpdated != null) {
179+
agent.removeListener('updateHookSettings', onSettingsUpdated);
180+
}
181+
164182
// If we received 'shutdown' from `agent`, we assume the `bridge` is already shutting down,
165183
// and that caused the 'shutdown' event on the `agent`, so we don't need to call `bridge.shutdown()` here.
166184
hook.emit('shutdown');
@@ -290,6 +308,7 @@ type ConnectWithCustomMessagingOptions = {
290308
onMessage: (event: string, payload: any) => void,
291309
nativeStyleEditorValidAttributes?: $ReadOnlyArray<string>,
292310
resolveRNStyle?: ResolveNativeStyle,
311+
onSettingsUpdated?: (settings: DevToolsHookSettings) => void,
293312
};
294313

295314
export function connectWithCustomMessagingProtocol({
@@ -298,7 +317,9 @@ export function connectWithCustomMessagingProtocol({
298317
onMessage,
299318
nativeStyleEditorValidAttributes,
300319
resolveRNStyle,
320+
onSettingsUpdated,
301321
}: ConnectWithCustomMessagingOptions): Function {
322+
const hook: ?DevToolsHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
302323
if (hook == null) {
303324
// DevTools didn't get injected into this page (maybe b'c of the contentType).
304325
return;
@@ -334,7 +355,14 @@ export function connectWithCustomMessagingProtocol({
334355
}
335356

336357
const agent = new Agent(bridge);
358+
if (onSettingsUpdated != null) {
359+
agent.addListener('updateHookSettings', onSettingsUpdated);
360+
}
337361
agent.addListener('shutdown', () => {
362+
if (onSettingsUpdated != null) {
363+
agent.removeListener('updateHookSettings', onSettingsUpdated);
364+
}
365+
338366
// If we received 'shutdown' from `agent`, we assume the `bridge` is already shutting down,
339367
// and that caused the 'shutdown' event on the `agent`, so we don't need to call `bridge.shutdown()` here.
340368
hook.emit('shutdown');

0 commit comments

Comments
 (0)