Socket
Socket
Sign inDemoInstall

react-devtools-inline

Package Overview
Dependencies
2
Maintainers
7
Versions
86
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    react-devtools-inline

Embed react-devtools within a website


Version published
Weekly downloads
60K
decreased by-23.56%
Maintainers
7
Install size
27.6 MB
Created
Weekly downloads
 

Changelog

Source

15.2.0 (July 1, 2016)

React

  • Add error codes to production invariants, with links to the view the full error text. (@keyanzhang in #6948)
  • Include component stack information in PropType validation warnings. (@troydemonbreun in #6398, @sophiebits in #6771)
  • Include component stack information in key warnings. (@keyanzhang in #6799)
  • Stop validating props at mount time, only validate at element creation. (@keyanzhang in #6824)
  • New invariant providing actionable error in missing instance case. (@yungsters in #6990)
  • Add React.PropTypes.symbol to support ES2015 Symbols as props. (@puradox in #6377)
  • Fix incorrect coercion of ref or key that are undefined in development (@gaearon in #6880)
  • Fix a false positive when passing other element’s props to cloneElement (@ericmatthys in #6268)
  • Warn if you attempt to define childContextTypes on a functional component (@Aweary in #6933)

React DOM

  • Add warning for unknown properties on DOM elements. (@jimfb in #6800, @gm758 in #7152)
  • Properly remove attributes from custom elements. (@grassator in #6748)
  • Fix invalid unicode escape in attribute name regular expression. (@nbjahan in #6772)
  • Add onLoad handling to <link> element. (@roderickhsiao in #6815)
  • Add onError handling to <source> element. (@wadahiro in #6941)
  • Handle value and defaultValue more accurately in the DOM. (@jimfb in #6406)
  • Fix events issue in environments with mutated Object.prototype. (@Weizenlol in #6886)
  • Fix issue where is="null" ended up in the DOM in Firefox. (@darobin in #6896)
  • Improved performance of text escaping by using escape-html. (@aickin in #6862)
  • Fix issue with dangerouslySetInnerHTML and SVG in Internet Explorer. (@joshhunt in #6982)
  • Fix issue with <textarea> placeholders. (@jimfb in #7002)
  • Fix controlled vs uncontrolled detection of <input type="radio"/>. (@jimfb in #7003)
  • Improve performance of updating text content. (@trueadm in #7005)
  • Ensure controlled <select> components behave the same on initial render as they do on updates. (@yiminghe in #5362)

React Perf Add-on

React CSSTransitionGroup Add-on

React Native Renderer

  • Dependencies on React Native modules use CommonJS requires instead of providesModule. (@davidaurelio in #6715)

Readme

Source

react-devtools-inline

This package can be used to embed React DevTools into browser-based tools like CodeSandbox, StackBlitz, and Replay.

If you're looking for the standalone React DevTools UI, we suggest using react-devtools instead of using this package directly.


Note that this package (and the DevTools UI) relies on several experimental APIs that are only available in the experimental release channel. This means that you will need to install react@experimental and react-dom@experimental.


Usage

This package exports two entry points: a frontend (to be run in the main window) and a backend (to be installed and run within an iframe1).

The frontend and backend can be initialized in any order, but the backend must not be activated until the frontend initialization has completed. Because of this, the simplest sequence is:

  1. Frontend (DevTools interface) initialized in the main window.
  2. Backend initialized in an iframe.
  3. Backend activated.

1 Sandboxed iframes are supported.

Backend APIs

initialize(windowOrGlobal)

Installs the global hook on the window/global object. This hook is how React and DevTools communicate.

This method must be called before React is loaded. (This includes import/require statements and <script> tags that include React.)

activate(windowOrGlobal)

Lets the backend know when the frontend is ready. It should not be called until after the frontend has been initialized, else the frontend might miss important tree-initialization events.

Example

import { activate, initialize } from 'react-devtools-inline/backend';

// This should be the iframe the React application is running in.
const iframe = document.getElementById(frameID);
const contentWindow = iframe.contentWindow;

// Call this before importing React (or any other packages that might import React).
initialize(contentWindow);

// Initialize the frontend...

// Call this only once the frontend has been initialized.
activate(contentWindow);

Frontend APIs

initialize(windowOrGlobal)

Configures the DevTools interface to listen to the window (or global object) the backend was injected into. This method returns a React component that can be rendered directly.

Because the DevTools interface makes use of several new React concurrent features (like Suspense) it should be rendered using ReactDOMClient.createRoot instead of ReactDOM.render.

Example

import { initialize } from 'react-devtools-inline/frontend';

// This should be the iframe the backend hook has been installed in.
const iframe = document.getElementById(frameID);
const contentWindow = iframe.contentWindow;

// This returns a React component that can be rendered into your app.
// e.g. render(<DevTools {...props} />);
const DevTools = initialize(contentWindow);

Advanced examples

Supporting named hooks

DevTools can display hook "names" for an inspected component, although determining the "names" requires loading the source (and source-maps), parsing the code, and inferring the names based on which variables hook values get assigned to. Because the code for this is non-trivial, it's lazy-loaded only if the feature is enabled.

To configure this package to support this functionality, you'll need to provide a prop that dynamically imports the extra functionality:

// Follow code examples above to configure the backend and frontend.
// When rendering DevTools, the important part is to pass a 'hookNamesModuleLoaderFunction' prop.
const hookNamesModuleLoaderFunction = () => import('react-devtools-inline/hookNames');

// Render:
<DevTools
  hookNamesModuleLoaderFunction={hookNamesModuleLoaderFunction}
  {...otherProps}
/>;

Configuring a same-origin iframe

The simplest way to use this package is to install the hook from the parent window. This is possible if the iframe is not sandboxed and there are no cross-origin restrictions.

import {
  activate as activateBackend,
  initialize as initializeBackend
} from 'react-devtools-inline/backend';
import { initialize as initializeFrontend } from 'react-devtools-inline/frontend';

// The React app you want to inspect with DevTools is running within this iframe:
const iframe = document.getElementById('target');
const { contentWindow } = iframe;

// Installs the global hook into the iframe.
// This must be called before React is loaded into that frame.
initializeBackend(contentWindow);

// Initialize DevTools UI to listen to the hook we just installed.
// This returns a React component we can render anywhere in the parent window.
// This also must be called before React is loaded into the iframe
const DevTools = initializeFrontend(contentWindow);

// React application can be injected into <iframe> at any time now...
// Note that this would need to be done via <script> tag injection,
// as setting the src of the <iframe> would load a new page (without the injected backend).

// <DevTools /> interface can be rendered in the parent window at any time now...
// Be sure to use ReactDOMClient.createRoot() to render this component.

// Let the backend know the frontend is ready and listening.
activateBackend(contentWindow);

Configuring a sandboxed iframe

Sandboxed iframes are also supported but require more complex initialization.

iframe.html

import { activate, initialize } from "react-devtools-inline/backend";

// The DevTools hook needs to be installed before React is even required!
// The safest way to do this is probably to install it in a separate script tag.
initialize(window);

// Wait for the frontend to let us know that it's ready.
function onMessage({ data }) {
  switch (data.type) {
    case "activate-backend":
      window.removeEventListener("message", onMessage);

      activate(window);
      break;
    default:
      break;
  }
}

window.addEventListener("message", onMessage);

main-window.html

import { initialize } from "react-devtools-inline/frontend";

const iframe = document.getElementById("target");
const { contentWindow } = iframe;

// Initialize DevTools UI to listen to the iframe.
// This returns a React component we can render anywhere in the main window.
// Be sure to use ReactDOMClient.createRoot() to render this component.
const DevTools = initialize(contentWindow);

// Let the backend know to initialize itself.
// We can't do this directly because the iframe is sandboxed.
// Only initialize the backend once the DevTools frontend has been initialized.
iframe.onload = () => {
  contentWindow.postMessage(
    {
      type: "activate-backend"
    },
    "*"
  );
};

Advanced: Custom "wall"

Below is an example of an advanced integration with a website like Replay.io or Code Sandbox's Sandpack (where more than one DevTools instance may be rendered per page).

import {
  activate as activateBackend,
  createBridge as createBackendBridge,
  initialize as initializeBackend,
} from 'react-devtools-inline/backend';
import {
  createBridge as createFrontendBridge,
  createStore,
  initialize as createDevTools,
} from 'react-devtools-inline/frontend';

// DevTools uses "message" events and window.postMessage() by default,
// but we can override this behavior by creating a custom "Wall" object.
// For example...
const wall = {
  _listeners: [],
  listen(listener) {
    wall._listeners.push(listener);
  },
  send(event, payload) {
    wall._listeners.forEach(listener => listener({event, payload}));
  },
};

// Initialize the DevTools backend before importing React (or any other packages that might import React).
initializeBackend(contentWindow);

// Prepare DevTools for rendering.
// To use the custom Wall we've created, we need to also create our own "Bridge" and "Store" objects.
const bridge = createFrontendBridge(contentWindow, wall);
const store = createStore(bridge);
const DevTools = createDevTools(contentWindow, { bridge, store });

// You can render DevTools now:
const root = createRoot(container);
root.render(<DevTools {...otherProps} />);

// Lastly, let the DevTools backend know that the frontend is ready.
// To use the custom Wall we've created, we need to also pass in the "Bridge".
activateBackend(contentWindow, {
  bridge: createBackendBridge(contentWindow, wall),
});

Alternately, if your code can't share the same wall object, you can still provide a custom Wall that connects a specific DevTools frontend to a specific backend like so:

const uid = "some-unique-string-shared-between-both-pieces";
const wall = {
  listen(listener) {
    window.addEventListener("message", (event) => {
      if (event.data.uid === uid) {
        listener(event.data);
      }
    });
  },
  send(event, payload) {
    window.postMessage({ event, payload, uid }, "*");
  },
};

Advanced: Node + browser

Below is an example of an advanced integration that could be used to connect React running in a Node process to React DevTools running in a browser.

Sample Node backend
const {
  activate,
  createBridge,
  initialize,
} = require('react-devtools-inline/backend');
const { createServer } = require('http');
const SocketIO = require('socket.io');

const server = createServer();
const socket = SocketIO(server, {
  cors: {
    origin: "*",
    methods: ["GET", "POST"],
    allowedHeaders: [],
    credentials: true
  }
});
socket.on('connection', client => {
  const wall = {
    listen(listener) {
      client.on('message', data => {
        if (data.uid === UID) {
          listener(data);
        }
      });
    },
    send(event, payload) {
      const data = {event, payload, uid: UID};
      client.emit('message', data);
    },
  };

  const bridge = createBridge(global, wall);

  client.on('disconnect', () => {
    bridge.shutdown();
  });

  activate(global, { bridge });
});
socket.listen(PORT);
Sample Web frontend
import { createElement } from 'react';
import { createRoot } from 'react-dom/client';
import {
  createBridge,
  createStore,
  initialize as createDevTools,
} from 'react-devtools-inline/frontend';
import { io } from "socket.io-client";

let root = null;

const socket = io(`http://${HOST}:${PORT}`);
socket.on("connect", () => {
  const wall = {
    listen(listener) {
      socket.on("message", (data) => {
        if (data.uid === UID) {
          listener(data);
        }
      });
    },
    send(event, payload) {
      const data = { event, payload, uid: UID };
      socket.emit('message', data);
    },
  };

  const bridge = createBridge(window, wall);
  const store = createStore(bridge);
  const DevTools = createDevTools(window, { bridge, store });

  root = createRoot(document.getElementById('root'));
  root.render(createElement(DevTools));
});
socket.on("disconnect", () => {
  root.unmount();
  root = null;
});

Local development

You can also build and test this package from source.

Prerequisite steps

DevTools depends on local versions of several NPM packages1 also in this workspace. You'll need to either build or download those packages first.

1 Note that at this time, an experimental build is required because DevTools depends on the createRoot API.

Build from source

To build dependencies from source, run the following command from the root of the repository:

yarn build-for-devtools

Download from CI

To use the latest build from CI, go to scripts/release/ and run the following commands:

yarn
./download-experimental-build.js --commit=main

Build steps

Once the above packages have been built or downloaded, you can watch for changes made to the source code and automatically rebuild by running:

yarn start

To test package changes, refer to the react-devtools-shell README.

FAQs

Last updated on 08 May 2024

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc