27

I have started learning React and I am not able to understand why is the console.log logging twice. Below is my code and when I inspect it in chrome it shows the word 'random-text' twice instead of once.

import React, { Component } from "react";

class Counter extends Component {
  state = {
    count: 0

  };



  render() {
    console.log('random-text');

    return (
      <div>
        <span className={this.getBaadgeClasses()}>{this.formatCount()}</span>
        <button
          onClick={this.handleIncrement}
          className="btn btn-success m-2"
        >
          Increment
        </button>

        {/* <ul>
          {this.state.tags.map((tag) => (
            <li key={tag}>{tag}</li>
          ))}
        </ul> */}
      </div>
    );
  }

  getBaadgeClasses() {
    let classes = "badge m-2 badge-";
    classes += this.state.count === 0 ? "warning" : "primary";
    return classes;
  }

  formatCount() {
    const { count } = this.state;
    return count === 0 ? "Zero" : count;
  }

  handleIncrement = () => {
    this.setState({count: this.state.count + 1})
  }

}

export default Counter;
HBK8396
  • 481
  • 1
  • 5
  • 9
  • I believe it's happening because you are calling getBaadgeClasses inside the render method, causing the component to re-render. Try removing this call and see what you get. – David G Jun 04 '20 at 01:46
  • `render` method is in react's lifecycle. it'll be triggered when your component's props or state changed. – Narro Jun 04 '20 at 01:47
  • @DavidG I tried removing the getBadgeClasses inside the render method but it still logged twice.. Infact even with an empty div in render it logged twice.... – HBK8396 Jun 04 '20 at 13:36

3 Answers3

41

The render function is a lifecycle function, called during the "render phase"

enter image description here

react lifecycle methods diagram

Notice that these functions are pure functions, and can be paused, aborted, or restarted by React. This means react can call render almost any number of times to reconcile the virtualDOM with the actual DOM.

Detecting unexpected side effects

Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:

  • Class component constructor, render, and shouldComponentUpdate methods
  • Class component static getDerivedStateFromProps method
  • Function component bodies
  • State updater functions (the first argument to setState)
  • Functions passed to useState, useMemo, or useReducer

Note:

This only applies to development mode. Lifecycles will not be double-invoked in production mode.

If you truly want a one-to-one console log when the component updates use one of the other lifecycle functions, like componentDidUpdate to do the side-effect of logging details.

class Counter extends Component {
  state = {
    count: 0
  };

  componentDidUpdate() {
    console.log("random-text");
  }

  render() {
    return (
      <div>
        <span className={this.getBaadgeClasses()}>{this.formatCount()}</span>
        <button onClick={this.handleIncrement} className="btn btn-success m-2">
          Increment
        </button>

        {/* <ul>
          {this.state.tags.map((tag) => (
            <li key={tag}>{tag}</li>
          ))}
        </ul> */}
      </div>
    );
  }

  getBaadgeClasses() {
    let classes = "badge m-2 badge-";
    classes += this.state.count === 0 ? "warning" : "primary";
    return classes;
  }

  formatCount() {
    const { count } = this.state;
    return count === 0 ? "Zero" : count;
  }

  handleIncrement = () => {
    this.setState({ count: this.state.count + 1 });
  };
}

Edit use lifecycle function to log

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • Thank you very much for you answer. My doubt is will the react re-render even if there is no change in the state and props? Even with an empty div, the react is logging it twice. Why is this happening? I am a beginner so please excuse if the doubt sounds silly. – HBK8396 Jun 04 '20 at 13:44
  • 5
    @HBK8396 I believe you are conflating the react framework invoking the render function (to compute a diff) with it committing anything to the DOM. Read the description of the "commit phase": "Can work with DOM, *run side effects*, schedule updates" and look at the lifecycle functions where you can do this. React traverses the entire virtualDOM tree and invokes `render` on every component, *then* it compares the output, *then* commits the diff. Even a component that renders static output (or `null` even) will have its render function invoked during reconciliation. – Drew Reese Jun 04 '20 at 15:39
  • I understand it now sir. Everything is quite clear and thank you very much. – HBK8396 Jun 04 '20 at 16:39
  • 1
    This answer is good, for more information this would help: https://reactjs.org/docs/strict-mode.html – Pouria Moosavi Oct 20 '20 at 09:52
28

When you create this project, this project enables Strict Mode automatically. So, To solve this problem firstly open index.js file in your project and then disable strict mode.

Step 1: when you open index.js file then you will see something like this,

root.render(
   <React.StrictMode>
    <App />
   </React.StrictMode>
);

Step2: Now do this,

root.render(
  // <React.StrictMode>
    <App />
  // </React.StrictMode>
);

I hope this will help you. Thank You

Florian Motteau
  • 3,467
  • 1
  • 22
  • 42
Tanvir Hasan
  • 281
  • 3
  • 2
9

The React team is no longer silencing console methods during the double render in Strict Mode. If you do not want to remove Strict Mode, like @Florian Motteau mentions, then you can go into React Dev Tools and check the box Hide logs during second render in Strict Mode. See screenshot below:

enter image description here

Here is the quote from the React Team, as well as the link to the discussion on their Github page.

In Strict Mode, React double invokes render methods in order to flush out potential side effects. During the second render, React used to automatically silence console methods (ex. console.log() and console.warn()) to reduce the noise of multiple repeat logs. However, this ended up causing a lot of confusion for developers during debugging, so we are changing this behavior. - React Team

dave4jr
  • 1,131
  • 13
  • 18