skip to Main Content

My problem

The code is simple. When you switch to any new button, it will log the updated sourceType, then "My Log".

You start off at the posts tab, then you clicked users tab, it will log "users" and "My log", which I expect.
Then if you click on "users" button again, why does it log "My Log"?
Then if you click "users" button again, no matter how many times, why does it log nothing?

Does it have anything to do with lifecycles? Help me out here, thank you!

import React, { useState, useEffect } from "react";

export default function App() {
  const [sourceType, setSourceType] = useState("posts");

  useEffect(() => {
    console.log(sourceType);
  }, [sourceType]);

  console.log("My Log");

  return (
    <div>
      <button
        onClick={() => {
          setSourceType("posts");
        }}
      >
        {" "}
        Posts{" "}
      </button>

      <button
        onClick={() => {
          setSourceType("users");
        }}
      >
        {" "}
        Users{" "}
      </button>

      <button
        onClick={() => {
          setSourceType("comments");
        }}
      >
        {" "}
        Comments{" "}
      </button>

      <h1> {sourceType} </h1>
    </div>
  );
}

My expectation

When you are already in the new tab or button, I expect that it will not cause rerender, so it should not print "My Log", but it did.

So, I continue to click. I expect it to be consistant to print, but it does not print "my log" anymore. I understand that it is great for performance. But I don’t undertsand why it logged before.

2

Answers


  1. console.log('My Log') is in the body of the functional component. Thus, any time a parent state changes, an event handler activates, component state updates occur, or component reconciliations occur, that "My Log" console log will get called.

    In your case, you’re updating the state of this functional component and initiating a rerender, even though it’s not dependent on the variable you’re targetting with your useEffect.

    Login or Signup to reply.
  2. The behavior you are observing is expected and is a result of how React’s rendering and re-rendering process works. Let me explain why you are seeing the logs as you described:

    1. Initial Render: When the component is first rendered, the initial value of sourceType is "posts," and the component is mounted. The useEffect hook is triggered, logging "posts" to the console.

    2. First Button Click (Switching from "posts" to "users"): When you click the "Users" button, the state is updated, and the component re-renders. The useEffect hook is triggered again, logging "users" to the console. After the re-render, the component also logs "My Log."

    3. Second Button Click (Switching from "users" to "users"): When you click the "Users" button again, the state is updated to the same value ("users"). React is designed to be efficient, and when a component re-renders with the same state, it will skip rendering the component again. Since the state remains the same ("users"), the useEffect hook is not triggered, and "My Log" is not printed again.

    4. Subsequent Button Clicks (Switching between different tabs): React will only trigger re-renders when the state changes. If you continue clicking between different buttons ("Posts," "Users," "Comments"), the useEffect hook will be triggered each time the state (sourceType) changes. However, when you click the same button again (e.g., clicking "Users" after already being on the "Users" tab), React will skip re-rendering, and "My Log" will not be printed.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search