Umut Palabiyik
Umut Palabiyik

Reputation: 323

React render component even though state doesnt change

import { useState } from "react";

export default function App() {
  console.log("rendered...")
  const [count, setCount] = useState(0);

  const increaseCount = () => {
    setCount(count + 1);
  };

  const setFourValue = () => {
    setCount(4);
  };
  return (
    <div className="App">
      <div
        style={{ display: "flex", alignItems: "center", columnGap: ".25rem" }}
      >
        <button onClick={increaseCount}>Increase</button>
        <button onClick={setFourValue}>Set 4</button>
        <span>{count}</span>
      </div>
    </div>
  );
}

I try to figure out when and how component render. Situation that i try to is i increased count to 4 and now my count value is 4. But i click to 'Set 4' button my count value is still 4 but still component re-rendered. After that if click again 'Set 4' button component doesn't re-render. Why ?

Upvotes: 1

Views: 77

Answers (4)

Nice Books
Nice Books

Reputation: 1861

There's a problem with your increaseCount function. When you are updating a state property using its previous value, the callback argument must be used. This is due to the asynchronous nature of state updates. (See https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous)

const increaseCount = () => {
    setCount((count) => (count + 1));
};

It could probably be the reason why the count was 3 instead of 4 as said by @Tim van Dam.

Upvotes: 1

Tushar Shahi
Tushar Shahi

Reputation: 20451

Most answers here are correct in explaining how the callback pattern of setState should be preferred when the updated state value depends on the previous state value. But one part of the question is still pending

But i click to 'Set 4' button my count value is still 4 but still component re-rendered.

I created this sandbox and this indeed happens.

If we do setCount(4) from increaseCount and then from setFourValue, both trigger a rerender.

The answer is here though

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.

And React indeed does not go deeper into the tree, which you can check by uncommenting <Child>. It is not going deeper into the tree as <Child> will not rerender, even if <App> does.

Upvotes: 0

Tim van Dam
Tim van Dam

Reputation: 465

To add on to Barry's answer, when you set the count to4 the first time with setFourValue after increasing it to 4 with increaseCount, it actually isn't 4. Console log the count and you'll see that it's actually 3 even though it displays 4 on the screen.

Upvotes: 1

Barry Michael Doyle
Barry Michael Doyle

Reputation: 10608

In React, components will only re-render if a state or prop in the component change.

Setting 4 to 4 is not a change.

React is smart enough to not re-render unnecessarily.

Upvotes: 1

Related Questions