React Devtools

Strict Mode surfaces bugs in development by running effects twice, and React DevTools lets you inspect the live component tree without console.log.

May 15, 20263 min read4 / 7

After locking in keys and state updates, two more tools belong in the development setup before the app gets more complex: StrictMode and React DevTools. Both cost nothing to add and pay off immediately.

Strict Mode

Wrap the app in StrictMode in main.jsx:

JSX
import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import App from "./App"; createRoot(document.getElementById("root")).render( <StrictMode> <App /> </StrictMode> );

StrictMode does nothing in production. In development, it deliberately invokes your component functions and effects twice. That sounds annoying, but it is catching a specific class of bugs: side effects that are not properly cleaned up.

When you write a useEffect and React calls it twice, anything that should only happen once will break immediately. A fetch that fires twice reveals a missing abort signal. A subscription that registers twice reveals a missing cleanup function. A counter that increments by two instead of one reveals state mutation instead of state replacement.

The double-invoke behavior means: if your app works correctly under StrictMode, it is likely to behave correctly when React eventually uses features like concurrent rendering that can pause and restart rendering mid-flight.

React DevTools

Install the browser extension for Chrome or Firefox. Once installed, two new tabs appear in the browser DevTools panel:

Components -- shows the live React component tree. Click any component to see its current props and state on the right. No more console.log to check what props a component received.

React DevTools Components tab shows the live component tree with props and state ExpandReact DevTools Components tab shows the live component tree with props and state

Profiler -- records a render session and shows you which components rendered, how long each took, and why they re-rendered. Useful when you have a performance problem and need to find what is causing unnecessary renders.

Inspecting Live State

Click a component in the Components tab and the right panel shows its hooks. For a component using useState, you can see the current value. You can even edit the value directly in DevTools and watch the component re-render with the new value -- no code change needed. This is useful for testing edge cases quickly.

The $r Trick

Click any component in the Components tab and then switch to the Console tab. Type $r. The browser assigns $r to the currently selected React component instance, giving you access to its props and state from the console:

JavaScript
$r.props $r.props.pizzaType

This is the same idea as $0 for DOM elements in the Elements tab. It is handy for one-off debugging without adding console.log to the source.

NODE_ENV and Development-Only Tools

StrictMode and DevTools both key off the environment. Vite sets process.env.NODE_ENV to "development" during dev and "production" during builds. React uses this internally to gate the double-invoke behavior and certain warning messages.

You do not need to configure this. But it explains why adding a console.log inside a useEffect fires twice during development under StrictMode -- that is the system working as intended.

With the dev environment solid, the next logical step is extracting repeated fetch logic into a custom hook -- a pattern that clicks much faster once you can watch it in the Components tab.

The Essentials

  1. StrictMode wraps the app in main.jsx. It double-invokes effects in development to surface cleanup bugs. Zero production cost.
  2. Components tab in React DevTools shows the live component tree, props, and state. Click a component to inspect it; edit state directly to test edge cases.
  3. Profiler tab records render timing. Use it when you have a performance problem, not proactively.
  4. $r in the Console tab refers to the component selected in the Components tab -- a fast way to inspect its props without adding console.log.
  5. NODE_ENV is set automatically by Vite. Development-only behavior in React (double renders, warnings) disappears in production builds.

Further Reading and Watching