Jamāl
Jamāl

Reputation: 121

Why does react not re-render when content has changed due to change in global variable and setState is called?

Below is my test code,

import { useState } from "react";

let a = 5;
function App() {
    const [b, setB] = useState(0);

    const handler = () => {
        a++;
        console.log(a);
        setB(0);
    };

    return (
        <>
            <div style={{ "font-size": "4rem" }}>{a}</div>
            <button
                type="button"
                style={{ "font-size": "4rem" }}
                onClick={handler}
            >
                CLICK
            </button>
        </>
    );
}

export default App;

I had read that react calls render whenever there's a call to setState. So the VDOM is then rebuilt and then compared to the real DOM's snapshot. The real DOM is updated when there's an actual difference with its previous snapshot.

With this understanding, I don't see why the div is not re-rendered. Since the global variable a is incremented on every button click and immediately next setB(0) is called, I expected the new value of a to be displayed. However, when I instead do setB(1), the updated value of a is shown. This was a surprise to me since I didn't think that react compared the value of state to determine whether to re-render or not and just does so whenever a call to setState is made. Any insight into this will be much appreciated.

PS: I'm still a beginner in react and don't know many advanced concepts. The only hook I used till now is useState.

Upvotes: 0

Views: 592

Answers (2)

ValenciaHQ
ValenciaHQ

Reputation: 385

You need to read this to complete the idea:

https://es.reactjs.org/docs/reconciliation.html

Upvotes: 0

Nicholas Tower
Nicholas Tower

Reputation: 85022

I had read that react calls render whenever there's a call to setState.

That's close to true, but it's incomplete. React also tries to skip unnecessary work, so it will compare the old state with the new state (using ===), and skip the render if they're the same. So since you're always calling setB(0);, it's always 0, and the render keeps getting skipped.

Upvotes: 2

Related Questions