Why is my React component is rendering twice?

Solution 1:

You are running your app in strict mode. Go to index.js and comment strict mode tag. You will find a single render.

This happens is an intentional feature of the React.StrictMode. It only happens in development mode and should help to find accidental side effects in the render phase.

From the docs:

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:...

^ In this case the render function.

Official documentation of what might cause re-rendering when using React.StrictMode:

https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects

Solution 2:

React is rendering the component before getPoints finishing the asynchronous operation.

So the first render shows the initial state for points which is 0, then componentDidMount is called and triggers the async operation.
When the async operation is done and the state been updated, another render is triggered with the new data.

If you want, you can show a loader or an indicator that the data is being fetched and is not ready yet to display with conditional rendering.

Just add another Boolean key like isFetching, set it to true when you call the server and set it to false when the data is received.

Your render can look something like this:

  render() {
    const { isFetching } = this.state;
    return (
      <div>
        {isFetching ? (
          <div>Loading...</div>
        ) : (
          <div>
            <p>
              {this.state.phoneNumber} has {this.state.points} points...
            </p>
            <p>Would you like to redeem or add points?</p>
            <div>
              <button>Redeem Points</button>
              <button>Add Points</button>
            </div>
          </div>
        )}
      </div>
    );
  }

Solution 3:

This is because of React Strict Mode code.

Remove -> React.StrictMode, from ReactDOM.render code.

Will render 2 times on every re-render:

ReactDOM.render(
  <React.StrictMode>
<App />
  </React.StrictMode>,
  document.getElementById('root')
);

Will render 1 time:

ReactDOM.render(
  <>
<App />
  </>,
  document.getElementById('root')
);

PS no offence to people that are saying DONT worry about 'how many times it re-renders' ... if you are running a perpetual API fetch code every 1 second through a setTimeout and every time you use the API it costs you 0.01 cent, every single time it re-renders it fires the setTimeout function 2 times (which means you are doubling the calls every second), which means after 5 seconds you are running 1000+ setTimeouts each calling API at the same time and after 1 hour, this number will become a trillion+, so costs will become astranomical if you get it wrong. This issue is fixed by removing React.StrictMode, so code will WAI.

Solution 4:

React.StrictMode, makes it render twice, so that we do not put side effects in following locations

constructor
componentWillMount (or UNSAFE_componentWillMount)
componentWillReceiveProps (or UNSAFE_componentWillReceiveProps)
componentWillUpdate (or UNSAFE_componentWillUpdate)
getDerivedStateFromProps
shouldComponentUpdate
render
setState updater functions (the first argument)

All these methods are called more than once, so it is important to avoid having side-effects in them. If we ignore this principle it is likely to end up with inconsistent state issues and memory leaks.

React.StrictMode cannot spot side-effects at once, but it can help us find them by intentionally invoking twice some key functions.

These functions are:

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

This behaviour definitely has some performance impact, but we should not worry since it takes place only in development and not in production.
credit: https://mariosfakiolas.com/blog/my-react-components-render-twice-and-drive-me-crazy/