DEV Community

Cover image for Be careful with console.log when using React.StrictMode
Sebastian Stamm
Sebastian Stamm

Posted on

Be careful with console.log when using React.StrictMode

I recently came across an interesting phenomenon that can be reproduced with this minimal example:

let i = 0;

function App() {
  i++;
  console.log("render count:", i);
  return i;
}

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);
Enter fullscreen mode Exit fullscreen mode

A novice developer might look at this code and think:

Okay, we are rendering the App component, this increases the i counter, prints it to the console and returns it. So the result is "render count: 1" in the browser log and 1 is rendered on screen.

A more experienced developer knows that React.StrictMode causes the render function to be called twice. The idea is that this will help developers identify unintended side-effects in methods that should be side-effect free. You can read more about that here: https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects

So they might say:

React intentionally calls the render function twice, so i will be increased twice. We will see two entries in the browser console "render count: 1" and then "render count: 2" and the screen will render 2.

If you run this code however, there is only one console log saying "render count: 1", but the screen shows 2. You can see this for yourself here: https://codesandbox.io/s/strict-mode-logs-pynlw?file=/src/index.js

What is going on?

The only place where the value of i is increased is directly followed by a console.log statement, so if i would be set to 2, it should show up in the console.

It turns out that React is hijacking console.log and is replacing it with a function that does nothing on the second render pass. Here is the code that does that, this is the Pull Request that introduced this behavior and here is an open Pull Request to add an opt-out option to the dev tools.

In our example the render function is indeed executed twice, which leads to i being 2 when it is rendered on screen, but only the first console.log call actually logs to the console so it looks like the render function is only called once and i is only set to 1.

Personal Opinion

My personal opinion is that the decision to disable the logs for the second render pass was wrong. Developers not familiar with StrictMode will try to use console.log debugging to figure out why their functions are executed twice. If the logs for the second pass don't show up in the console, developers might falsely assume that the function is only executed once.

I would even argue that it undermines the concept of StrictMode. Printing to the console is a side-effect that StrictMode is supposed to expose. Intentionally obscuring it not only makes debugging harder, it prevents developers finding rogue log statements in render phase lifecycle methods that could cause problems in production once concurrent mode lands.

Top comments (3)

Collapse
 
yuns profile image
Yuns • Edited

Workaround is to use let log = console.log; and then print by log function. demo codesandbox.io/s/console-log-in-re...

Collapse
 
hanayashiki profile image
wang chenyu • Edited

Double logging might be a shock for beginners, but disabling it just delays the learning process. I just knew this despite of several react projects

Collapse
 
ko22009 profile image
Ruslan Kutliakhmetov • Edited

In react 18 we have console.log twice. And it's show twice only in dev. In prod we see only one.