Why does React render also if there is no change in state/ UI

93 views Asked by At

I have a logout button in header which only changes its state once on click from login to logout. So the total no. of renders should be 2

  1. when app loads
  2. on first click of login button which changes to text from login to logout

But an additional render is happening after this when I click logout button again though text has not changed.

Based on react core concept of diff algorithm, this re render without any text change should have not happened.

Can anyone help me out to explain why this additional render happening?

Link to code : https://playcode.io/1688044

import { useState } from 'react';
import { LOGO_URL } from '../utils/constants';

const Header = () => {
  const [btnName, setBtnName] = useState('Login');
  console.log('Header rendered');
  return (
    <div className='header'>
      <div className='logo-container'>
        <img className='logo' src={LOGO_URL} />
      </div>
      <div className='nav-items'>
        <ul>
          <li>Home</li>
          <li>About us</li>
          <li>Contact</li>
          <li>Cart</li>
          <button
            className='login-btn'
            onClick={() => {
              setBtnName('Logout');
            }}
          >
            {btnName}
          </button>
        </ul>
      </div>
    </div>
  );
};
export default Header

I was expecting the component to render only twice

  1. Initial render
  2. On click of button first time since it changes from Login to Logout

But it is rendering one more time when I click on button though text remains the same as Logout

2

There are 2 answers

0
Mariya On

This is a feature of React where it does an extra re-render before deciding to 'bail out' which means stop rendering child components. This is because there may be an inline reducer which may still be running and so this extra re-render is just to make sure that it is safe to bailout.

This was extensively discussed here. You can read about reducers here.

0
Akeel Ahmed Qureshi On

After applying this it will not render one more time when You click on button but text remains the same as Logout

import React, { useState, memo } from 'react';

const Header = () => {
  const [btnName, setBtnName] = useState('Login');
  console.log('Header rendered');

  return (
    <div className='header'>
 <div className='logo-container'>
      </div>
      <div className='nav-items'>
         <ul>
         <li>Home</li>
         <li>About us</li>
          <li>Contact</li>
          <li>Cart</li>
      <button
        className='login-btn'
        onClick={() => {
          if (btnName !== 'Logout') {
            setBtnName('Logout');
          }
        }}
      >
        {btnName}
      </button>
        </ul>
      </div>
    </div>
  );
};

export default memo(Header);