Skip to content

Commit 0455dfb

Browse files
committed
Add support for React Devtools
1 parent db3e8de commit 0455dfb

8 files changed

Lines changed: 103 additions & 11 deletions

File tree

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ root.render(
160160
- [Connection scope](#connection-scope)
161161
- [Human player scope](#human-player-scope)
162162
- [Global scope](#global-scope)
163+
- [Using React Devtools](#using-react-devtools)
163164
- [Development](#development)
164165

165166
## Requirements
@@ -976,6 +977,22 @@ function App() {
976977
}
977978
```
978979

980+
## Using React Devtools
981+
982+
React Node InSim supports [React Devtools](https://github.com/facebook/react/tree/master/packages/react-devtools) out of the box. To enable integration with React Devtools in your application, first ensure you have installed the optional `react-devtools-core` dependency, and then run your app with the `DEV=true` environment variable:
983+
984+
```shell
985+
DEV=true npm start
986+
```
987+
988+
Then, start React Devtools itself:
989+
990+
```shell
991+
npx react-devtools
992+
```
993+
994+
After it starts, you should see the component tree of your InSim app. You can even inspect and change the props of components, and see the results immediately in LFS, without restarting it.
995+
979996
## Development
980997

981998
### Requirements

examples/index.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ inSim.connect({
2828
Host: host,
2929
Port: process.env.PORT ? parseInt(process.env.PORT, 10) : 29999,
3030
Admin: process.env.ADMIN ?? '',
31-
Flags: host === '127.0.0.1' ? InSimFlags.ISF_LOCAL : undefined,
31+
Flags: InSimFlags.ISF_LOCAL,
3232
});
3333

3434
const root = createRoot(inSim);
@@ -37,15 +37,15 @@ root.render(
3737
<StrictMode>
3838
<ConnectionsPlayersProvider>
3939
<PlayersAndConnectionsExample />
40-
<ScopesExample />
41-
<PacketHooksExample />
42-
<FlexExample isEditorVisible={false} />
43-
<ButtonExample />
44-
<GridExample />
45-
<StackExample />
46-
<ToggleButtonExample />
47-
<ToggleButtonGroupExample />
48-
<TextBoxExample />
40+
{/*<ScopesExample />*/}
41+
{/*<PacketHooksExample />*/}
42+
{/*<FlexExample isEditorVisible={false} />*/}
43+
{/*<ButtonExample />*/}
44+
{/*<GridExample />*/}
45+
{/*<StackExample />*/}
46+
{/*<ToggleButtonExample />*/}
47+
{/*<ToggleButtonGroupExample />*/}
48+
{/*<TextBoxExample />*/}
4949
</ConnectionsPlayersProvider>
5050
</StrictMode>,
5151
);

package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@
3939
},
4040
"peerDependencies": {
4141
"node-insim": "^0.9.1 || 1 || 2 || 3 || 4 || 5",
42-
"react": ">=18"
42+
"react": ">=18",
43+
"react-devtools-core": "^6.1.5"
44+
},
45+
"peerDependenciesMeta": {
46+
"react-devtools-core": {
47+
"optional": true
48+
}
4349
},
4450
"dependencies": {
4551
"@types/react-reconciler": "^0.28.2",
@@ -57,6 +63,7 @@
5763
"@types/node": "^18.11.9",
5864
"@types/ramda": "^0.30.0",
5965
"@types/react": "^18.2.23",
66+
"@types/ws": "^8.18.1",
6067
"@typescript-eslint/eslint-plugin": "^5.22.0",
6168
"@typescript-eslint/parser": "^5.22.0",
6269
"@vitest/coverage-v8": "3.2.1",
@@ -71,6 +78,7 @@
7178
"npm-run-all": "^4.1.5",
7279
"prettier": "^2.6.2",
7380
"react": "^18.2.0",
81+
"react-devtools-core": "^6.1.5",
7482
"rimraf": "^5.0.5",
7583
"tsx": "^3.12.6",
7684
"typescript": "^4.9.5",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import ws from 'ws';
2+
3+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4+
const customGlobal = global as any;
5+
6+
// These things must exist before importing `react-devtools-core`
7+
customGlobal.WebSocket ||= ws;
8+
customGlobal.window ||= global;
9+
customGlobal.self ||= global;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import './devtools-window-polyfill.js';
2+
3+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
4+
// @ts-expect-error
5+
import * as devtools from 'react-devtools-core';
6+
7+
devtools.initialize();
8+
devtools.connectToDevTools();

src/lib/renderer/inSim/createRoot.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ export function createRoot(
6666
null,
6767
);
6868

69+
if (process.env['DEV'] === 'true') {
70+
InSimRenderer.injectIntoDevTools({
71+
bundleType: 1,
72+
version: '18.2.0',
73+
rendererPackageName: 'react-node-insim',
74+
});
75+
}
76+
6977
roots.set(rootID, fiberRoot);
7078

7179
// When a connection leaves, remove their UCID from all buttons

src/lib/renderer/inSim/hostConfig.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,28 @@ import type {
1818
UpdatePayload,
1919
} from './types';
2020

21+
if (process.env['DEV'] === 'true') {
22+
try {
23+
require('../devtools/devtools.js');
24+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
25+
} catch (error: any) {
26+
if (error?.code === 'ERR_MODULE_NOT_FOUND') {
27+
console.warn(
28+
`
29+
The environment variable DEV is set to true, so React Node InSim tried to import \`react-devtools-core\`,
30+
but this failed as it was not installed. Debugging with React Devtools requires it.
31+
32+
To install use this command:
33+
34+
$ npm install --save-dev react-devtools-core
35+
`.trim() + '\n',
36+
);
37+
} else {
38+
throw error;
39+
}
40+
}
41+
}
42+
2143
const NO_CONTEXT = {};
2244
let instanceCounter = 0;
2345

yarn.lock

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,13 @@
631631
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.3.tgz#9a726e116beb26c24f1ccd6850201e1246122e04"
632632
integrity sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==
633633

634+
"@types/ws@^8.18.1":
635+
version "8.18.1"
636+
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9"
637+
integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==
638+
dependencies:
639+
"@types/node" "*"
640+
634641
"@types/yoga-layout@1.9.2":
635642
version "1.9.2"
636643
resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.2.tgz#efaf9e991a7390dc081a0b679185979a83a9639a"
@@ -2519,6 +2526,14 @@ ramda@^0.30.1:
25192526
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.30.1.tgz#7108ac95673062b060025052cd5143ae8fc605bf"
25202527
integrity sha512-tEF5I22zJnuclswcZMc8bDIrwRHRzf+NqVEmqg50ShAZMP7MWeR/RGDthfM/p+BlqvF2fXAzpn8i+SJcYD3alw==
25212528

2529+
react-devtools-core@^6.1.5:
2530+
version "6.1.5"
2531+
resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-6.1.5.tgz#c5eca79209dab853a03b2158c034c5166975feee"
2532+
integrity sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==
2533+
dependencies:
2534+
shell-quote "^1.6.1"
2535+
ws "^7"
2536+
25222537
react-reconciler@0.29.0:
25232538
version "0.29.0"
25242539
resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.29.0.tgz#ee769bd362915076753f3845822f2d1046603de7"
@@ -3214,6 +3229,11 @@ wrappy@1:
32143229
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
32153230
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
32163231

3232+
ws@^7:
3233+
version "7.5.10"
3234+
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9"
3235+
integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==
3236+
32173237
yallist@^4.0.0:
32183238
version "4.0.0"
32193239
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"

0 commit comments

Comments
 (0)