Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my component rendering when useState is called with the same state?

I have a simple functional component with a boolean state. And buttons to change the state.

It is initially set to true so when I press the true-button, it does NOT render.

But if I press the false-button, it re-renders AND if I press false-button AGAIN, it will re-render even though the state is already set to false..

Could someone explain why the component re-renders when the state changes to the exact same state? How to prevent it from re-rendering?

import React, {useState} from 'react';

const TestHooks = () => {
    const [state, setState] = useState(true);
    console.log("rendering..", state);
    return(
        <div>
            <h1>{state.toString()}</h1>

            <button onClick={() => setState(true)}>true</button>

            <button onClick={() => setState(false)}>false</button>
        </div>
    )
}

export default TestHooks;
like image 611
oygen Avatar asked Feb 04 '23 17:02

oygen


2 Answers

From the react docs :

If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the Object.is comparison algorithm.)

Note that React may still need to render that specific component again before bailing out. That shouldn’t be a concern because React won’t unnecessarily go “deeper” into the tree. If you’re doing expensive calculations while rendering, you can optimize them with useMemo.

So your component will not re-render every time setState is called with the same state. It will re-render only 2 times and then bail out. That's just how react works and that should not be a concern except if you're doing some heavy calculations in the render method.

like image 111
Mohamed Ramrami Avatar answered Apr 27 '23 15:04

Mohamed Ramrami


It doesn't matter if the state value is already the same as the one you are trying to update it with. The fact is, setState() will re-render your component regardless, that's just what React does to ensure all changes (if any) are reflected in the UI.

If you want to avoid unnecessary re-renders, use an intermediary function to check if the state values are already equal before updating it.

import React, {useState} from 'react';

const TestHooks = () => {
    const [state, setState] = useState(true);

    const updateState = (boolean) => {
       if(boolean !== state){
          setState(boolean)
       }
    }

    console.log("rendering..", state);
    return(
        <div>
            <h1>{state.toString()}</h1>

            <button onClick={() => updateState(true)}>true</button>

            <button onClick={() => updateState(false)}>false</button>
        </div>
    )
}

export default TestHooks;
like image 26
Chris Ngo Avatar answered Apr 27 '23 15:04

Chris Ngo