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
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
.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:
Initial Render: When the component is first rendered, the initial value of
sourceType
is "posts," and the component is mounted. TheuseEffect
hook is triggered, logging "posts" to the console.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."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.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.