Skip to content

Instantly share code, notes, and snippets.

bvaughn /
Created Jul 8, 2021
Contributing to React DevTools

Intrested in contributing to React DevTools, but not sure where to start? This gist should hopefully get you going.

Install project dependencies

To get started, check out the React repo:

git clone

Next install dependencies:

cd <react-repo>

Adding Server Component support to DevTools is going to be a big lift, but generally speaking there are a few initial things to work out:

  • Updating the Flight server renderer to stream server component names/types to the client.
  • Adding a new hook to DevTools for the Flight client to call.
  • Merging the server component subtrees into the DevTools client tree.

Yesterday and today I've been thinking about this last item, and I'm feeling pretty stumped at the moment. Merging the trees isn't that difficult, but preserving the tree across client updates gets nasty when it comes to things like conditionally rendered elements.

Setting performance concerns aside, even if I were to undo the merged trees, apply the client updates, and then redo the merge– I'm still not sure we would definitely end up with the correct final state.

For example, consider the following client component that accepts "children" rendered by a server component:

bvaughn /
Created May 7, 2021
Multi-version browser extension proposal

Multi-version browser extension

This gist describes a challenge I've encountered while maintaining the React DevTools browser extension, and briefly explores one possible way to address that challenge. I would be happy to talk more in depth about this topic with anyone from Chrome/Firefox/Edge who would be interested in exploring.

The problem

The React DevTools browser extension supports all versions of react-dom released after 16.0.0-alpha (2017). We do this because developers often switch between projects built with different versions of React, and installing/enabling multiple versions of the extensions would be cumbersome.

This has a cost though: It adds a lot of complexity to the extension.

The implementation details of a library change frequently. Sometimes they change in a [straightforward way](

bvaughn /
Last active Jul 8, 2021
React DevTools: Unsupported backend version

Unsupported DevTools backend version

This page contains instructions for updating a local React DevTools application to match a version embedded in a renderer such as React Native. Instructions below cover NPM, Flipper, and React Native Debugger. If you use React DevTools in a different way, please let us know.

If you are viewing this page, you have likely seen one of the dialogs below:

Dialog displaying downgrade instructions for the React DevTools frontend to connect to an older backend version

<img width="400" height="233" alt="Dialog displaying upgrade instructions for the React DevTools fron

bvaughn / attaching-manual-event-listeners-in-passive-effect.js
Last active Apr 6, 2021
Attaching manual event listeners in a passive effect
View attaching-manual-event-listeners-in-passive-effect.js
// Simplistic (probably most common) approach.
// This approach assumes either that:
// 1) passive effects are always run synchronously, after paint, or
// 2) passive effects never attach handlers for bubbling events
// If both of the above are wrong (as can be the case) then problems might occur!
useEffect(() => {
const handleDocumentClick = (event: MouseEvent) => {
// It's possible that a "click" event rendered the component with this effect,
// in which case this event handler might be called for the same event (as it bubbles).
// In most scenarios, this is not desirable.
View ReactDOM-profiling.modern.js
* Copyright (c) Facebook, Inc. and its affiliates.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @noflow
* @nolint
* @preventMunge
* @preserve-invariant-messages
bvaughn / git-fork.js
Last active Jan 4, 2021
Utility to checkout a remote fork and branch from a GitHub PR
View git-fork.js
#!/usr/bin/env node
'use strict';
const { exec, execSync } = require('child_process');
const args = process.argv[0] === 'node'
? process.argv.slice(1)
: process.argv.slice(2);
View setFocusIfFocusable.js
function setFocusIfFocusable(node) {
if (node.nodeType !== Node.ELEMENT_NODE) {
// Text and comment nodes aren't focusable.
return false;
if (node.disabled === true) {
// Disabled elements can't be focused.
return false;
bvaughn /
Last active Jul 28, 2021
`useSubscription` and `useMutableSource` tearing and deopt behavior.

useSubscription and useMutableSource1 tearing and deopt behavior.

Mounting a new tree

The tree below represents a React application mounting. During mount, two components read from an external, mutable source. The first one (List) reads version 1 of that data and the second one (Item) reads version 2.


useSubscription (legacy mode)



How to try the new React Profiler

Before the holiday break, I was experimenting with a new profiler UI that may eventually make its way into a released version of the React DevTools. In the meanwhile, for anyone who is curious, here's how you can try this new profiler for yourself!

Building React

To start, you'll need an updated version of React that logs the new performance marks used by this profiler.

To do this, you'll need to check out PR 17772 and build it from source: yarn install && yarn build --type=NODE. (In the future I may publish an experimental release to NPM to simplify this step.)

Running the Profiler