> learned the whole concept from this simple project
🔄 What does re-render mean in useState
?
Re-render(means calling function)in React happens when we call the function returned by useState
(like setColor
) to update the state. A common confusion arises when we use:
const [Color, setColor] = useState("black");
Now, when I click a button and use setColor("green")
, the component re-renders.
Got it! Here's your original post with your tone and style kept intact — just added the new part you wanted, cleaned up the logic a bit, and kept it simple:
💭 But how does it work, if it's a const
?
React makes us feel like this variable is being recreated every time, but here’s the core truth:
const [Color, setColor] = useState("black");
-
"black"
is used only once — when the component mounts for the first time. - After that, React preserves the state between re-renders.
- Every time you call
setColor(...)
, React re-renders the component with the preserved state, not the original"black"
— means any value which was preserved like red, green etc.
Now even though you write:
const [Color, setColor] = useState("green");
in this re-render, React ignores "green"
because the state is already preserved with the latest value (like "green"
from previous update).
👉 Here's what’s really going on:
In every render, const [Color, setColor] = useState("black");
runs again — so Color
is getting created again because it's a const
(you can’t reassign it, but you can recreate it on every function call), and it's stored in the stack.
But when the value of Color
doesn’t change, it just takes the value from the preserved state.
However, setColor
is created only one time, and its reference is stored in the heap, so it doesn’t get recreated on every render.
🔁 Functions Re-execute, But State Persists
Yes, it's true that every time the component re-renders, the function (like App
or Main
) runs again and all its variables are freshly created in memory.
But React holds onto the state separately, outside of the function scope — that’s how useState
works.
🧠 Re-rendering for Primitive vs Non-Primitive Types
There’s a subtle behavior in useState
that’s often overlooked:
- For primitive values (
string
,number
,boolean
), if you callsetState
with the same value, React may still re-render, even though the value didn't change.
React doesn’t compare the old vs new primitive deeply — it just assumes change and re-renders.
- But for non-primitive types (
object
,array
,function
), React compares the reference. If the reference doesn't change, React won’t trigger a re-render.
So yes — it’s kind of ironic: React re-renders even when the primitive value is the same, but avoids re-rendering for same-reference non-primitives like objects,arrays.
✅ Optimization with useEffect
To prevent running side effects unnecessarily — like changing the background color — we use useEffect
.
useEffect(() => {
document.body.style.backgroundColor = Color;
}, [Color]);
This means:
- React will only update the background color if
Color
has actually changed. - Even though
useState
may trigger a re-render with the same primitive value,useEffect
won’t run unless the dependency (Color
) is different.
So this is where useEffect
helps us control unnecessary operations, especially with primitives.
⚠️ What if you don’t provide a dependency array?
useEffect(() => {
// runs on every render
});
This will cause the effect to run after every render, regardless of what changed.
But if you do:
useEffect(() => {
// runs only once — on initial render
}, []);
Then it runs only on first mount, just like componentDidMount
in class components.
🧩 Component Nesting, Reusability, and the Need for memo
Now the advanced bit.
When we render a UI, we often build it using multiple components. That’s how we split UI into reusable parts.
But here’s the issue:
If only one part of the UI is changing, React still re-runs all components used inside the main function — even if they didn't change.
That’s unnecessary, and over time, can slow things down.
🛡️ Enter React.memo
React provides a hook called memo
which helps with this:
const MemoizedComponent = React.memo(MyComponent);
This makes React:
- Render
MyComponent
only once initially - Then skip re-rendering it on future parent renders — unless props change
So now, if you're rendering multiple UIs like:
<MainUI />
<AnotherUI />
Even if only MainUI
needs to update, without memo
, both re-render. But with memo
, React skips re-rendering AnotherUI
if its props haven’t changed. Huge performance win.
⚠️ But yes — there's a tradeoff with memo
- When you wrap a component with
memo
, React adds extra comparison logic to check if the props have changed. - That’s some additional overhead.
- If your component always receives new props, it will re-render anyway, so
memo
doesn't help.
✅ So use memo
when:
- The component is large or expensive to render
- It receives stable props that don't change often
- The parent re-renders frequently
🎯 Final Conclusion
-
useState()
uses the initial value only once. - React re-renders the component when state changes — but keeps the latest state preserved.
- Re-renders recreate the function, but React gives you the last state back.
- React doesn’t optimize re-renders for primitives — but you can control side effects using
useEffect
. - For better performance, use
React.memo
to skip re-rendering components that don’t need to update.
This session helped me break some long-standing confusion. If you're also learning React, go deep — don't just learn syntax, understand the behavior.
React is not just about rendering UI — it’s about rendering smartly.
✨ If you found this helpful or you're on your own React journey — drop a like, share with a fellow dev, and feel free to comment your thoughts or doubts!
Let's learn together and build better. 💻🚀