React State & useState – Making Components Interactive
React becomes truly powerful when our UI isn't just displaying static information but can respond to user actions and change dynamically.
A button can change a counter.
A form can update its input.
A menu can open and close.
A like button can change from ❤️ to 🤍.
All of this requires State.
Today, we'll understand:
What is State?
Why do we need State?
State vs Props
useStateUpdating State
Multiple State variables
State with objects and arrays
Functional state updates
Why we should never mutate state directly
Common mistakes
Best practices
🧠 What Is State in React?
State is data that belongs to a component and can change over time.
For example:
function Counter() {
let count = 0;
return (
<div>
<p>Count: {count}</p>
<button>Increase</button>
</div>
);
}
We have a variable called count.
But if we change it:
count++;
React doesn't automatically know that it needs to update the UI.
That's where State comes in.
🔄 Why Do We Need State?
Consider a counter:
Count: 0
[ Increase ]
After clicking:
Count: 1
[ Increase ]
And again:
Count: 2
[ Increase ]
The data is changing.
Therefore, React needs a way to:
Store changing data
Detect that the data changed
Re-render the component
Display the updated value
React provides this through State.
⚛️ useState
useState is a React Hook that allows functional components to have state.
Basic syntax:
const [state, setState] = useState(initialValue);
For example:
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
}
export default Counter;
Let's break this down.
🔍 Understanding useState
const [count, setCount] = useState(0);
There are three important parts.
1. count
This is the current state value.
count
Initially:
0
2. setCount
This is the function used to update the state.
setCount(1);
or:
setCount(count + 1);
3. 0
This is the initial value.
useState(0);
So:
const [count, setCount] = useState(0);
means:
Create a state variable called
count, initially set to0, and give me a function calledsetCountto update it.
🔁 What Happens When State Changes?
Suppose:
const [count, setCount] = useState(0);
Initially:
count = 0
User clicks:
setCount(1);
React schedules the state update.
The component renders again.
Now:
count = 1
The UI becomes:
Count: 1
This is the basic React update cycle:
User Action
↓
State Update
↓
React Re-render
↓
Updated UI
🖱️ Handling Events With State
State becomes especially useful when combined with events.
Example:
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
function increaseCount() {
setCount(count + 1);
}
return (
<>
<h2>{count}</h2>
<button onClick={increaseCount}>
Increase
</button>
</>
);
}
When the button is clicked:
increaseCount
runs.
Then:
setCount(count + 1);
updates the state.
⚠️ Important: Don't Call the Function Immediately
Correct:
<button onClick={increaseCount}>
Increase
</button>
Incorrect:
<button onClick={increaseCount()}>
Increase
</button>
Why?
Because:
increaseCount()
calls the function immediately during rendering.
Instead, React needs a function reference that it can call when the event happens.
➕ Incrementing State
A simple approach is:
setCount(count + 1);
For example:
function increase() {
setCount(count + 1);
}
This works when the next state depends on the current state.
However, there's an even safer pattern.
🧮 Functional State Updates
When the new state depends on the previous state, use a function:
setCount(previousCount => previousCount + 1);
Example:
function increase() {
setCount(previousCount => previousCount + 1);
}
Here:
previousCount
represents the latest state value available to React.
This becomes especially important when performing multiple updates.
For example:
setCount(count + 1);
setCount(count + 1);
This does not necessarily produce the result you might expect.
Instead:
setCount(previous => previous + 1);
setCount(previous => previous + 1);
allows each update to build on the previous one.
🧩 Multiple State Variables
A component can have multiple pieces of state.
import { useState } from "react";
function Profile() {
const [name, setName] = useState("Saurabh");
const [age, setAge] = useState(23);
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
</div>
);
}
We can update them independently:
setName("Rahul");
and:
setAge(24);
Each state variable manages its own value.
🔢 State Can Store Different Data Types
State isn't limited to numbers.
It can store:
String
const [name, setName] = useState("Saurabh");
Number
const [age, setAge] = useState(23);
Boolean
const [isLoggedIn, setIsLoggedIn] = useState(false);
Array
const [skills, setSkills] = useState(["HTML", "CSS"]);
Object
const [user, setUser] = useState({
name: "Saurabh",
age: 23
});
🟢 Boolean State
Boolean state is extremely useful for UI interactions.
For example:
const [isVisible, setIsVisible] = useState(false);
Button:
<button onClick={() => setIsVisible(!isVisible)}>
Toggle
</button>
Then:
{isVisible && <p>Hello React!</p>}
Now clicking the button toggles the content.
📝 Example: Show / Hide Password
import { useState } from "react";
function Password() {
const [showPassword, setShowPassword] = useState(false);
return (
<div>
<input
type={showPassword ? "text" : "password"}
placeholder="Password"
/>
<button onClick={() => setShowPassword(!showPassword)}>
{showPassword ? "Hide" : "Show"}
</button>
</div>
);
}
Here state controls:
type={showPassword ? "text" : "password"}
This is a great example of state controlling UI.
📦 State With Objects
Suppose we have:
const [user, setUser] = useState({
name: "Saurabh",
age: 23
});
We should not directly modify the object.
❌ Don't do this:
user.name = "Rahul";
Instead, create a new object:
setUser({
...user,
name: "Rahul"
});
The spread operator copies the existing properties.
So:
{
...user,
name: "Rahul"
}
means:
Keep the existing user data, but replace
name.
📋 State With Arrays
Suppose:
const [skills, setSkills] = useState([
"HTML",
"CSS"
]);
To add JavaScript:
setSkills([
...skills,
"JavaScript"
]);
Now:
[
"HTML",
"CSS",
"JavaScript"
]
Again, we're creating a new array instead of modifying the existing one.
❌ Don't Mutate State Directly
This is one of the most important rules.
Avoid:
skills.push("React");
or:
user.name = "Rahul";
Instead:
setSkills([...skills, "React"]);
and:
setUser({
...user,
name: "Rahul"
});
Think of state as something you should replace with a new value, rather than directly modifying.
⚛️ Props vs State
This is extremely important.
| Props | State |
|---|---|
| Passed from parent | Managed by component |
| Read-only | Updated using setter |
| Used to pass data | Used for changing data |
| Parent controls the value | Component manages the value |
| Helps component communication | Helps component interaction |
Example:
function User({ name }) {
const [age, setAge] = useState(23);
return (
<div>
<h2>{name}</h2>
<p>{age}</p>
</div>
);
}
Here:
name
is a prop.
While:
age
is state.
🔄 Props + State Together
This is where React becomes really powerful.
Parent:
function App() {
const [name, setName] = useState("Saurabh");
return <Profile name={name} />;
}
Child:
function Profile({ name }) {
return <h2>{name}</h2>;
}
The flow is:
App State
↓
Props
↓
Profile Component
↓
UI
This is the foundation of React's one-way data flow.
🛒 Real-World Example: Shopping Cart
Imagine a shopping cart.
const [cartItems, setCartItems] = useState([]);
When a product is added:
setCartItems([
...cartItems,
product
]);
When removed, we could create a new array using:
setCartItems(
cartItems.filter(item => item.id !== product.id)
);
State is therefore useful for things like:
Shopping carts
Login status
Theme settings
Counters
Forms
Likes
Modals
Menus
Filters
Search results
🧠 The Most Important Mental Model
Don't think:
"I changed a variable."
Think:
"I requested React to update state."
For example:
setCount(count + 1);
The setter tells React:
State changed
↓
Component needs to render again
↓
React calculates the updated UI
↓
Browser displays the changes
⚠️ Common Mistakes
Mistake 1 — Direct mutation
❌
count++;
✅
setCount(count + 1);
Mistake 2 — Calling the event handler immediately
❌
onClick={increase()}
✅
onClick={increase}
Mistake 3 — Mutating arrays
❌
items.push(newItem);
✅
setItems([...items, newItem]);
Mistake 4 — Mutating objects
❌
user.name = "Rahul";
✅
setUser({
...user,
name: "Rahul"
});
Mistake 5 — Using state for everything
Not every variable needs to be state.
If a value doesn't need to change the UI when it changes, it may not need state.
For example:
const appName = "My App";
doesn't need to be state just because it is a variable.
🏆 Best Practices
1. Keep state minimal
Only store information that genuinely needs to be state.
2. Use meaningful names
Prefer:
const [isLoggedIn, setIsLoggedIn] = useState(false);
over:
const [x, setX] = useState(false);
3. Use functional updates when appropriate
setCount(prev => prev + 1);
4. Never mutate state directly
Create new arrays/objects instead.
5. Keep related state together
Don't unnecessarily create dozens of unrelated state variables.
6. Remember that state updates trigger rendering
Changing state isn't just changing a JavaScript variable — it affects the component's UI.
🚀 Complete Counter Example
Here's everything together:
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
function increase() {
setCount(prev => prev + 1);
}
function decrease() {
setCount(prev => prev - 1);
}
function reset() {
setCount(0);
}
return (
<div>
<h1>Counter</h1>
<h2>{count}</h2>
<button onClick={increase}>
+
</button>
<button onClick={decrease}>
-
</button>
<button onClick={reset}>
Reset
</button>
</div>
);
}
export default Counter;
This small application demonstrates the core idea of React State:
State
↓
UI
User Action
↓
State Update
↓
Re-render
↓
Updated UI
💡 My Biggest Takeaway
Today's biggest lesson for me was understanding that React State is what makes components dynamic and interactive.
Props allow components to receive data.
State allows components to manage changing data.
The most important pattern I learned today is:
const [value, setValue] = useState(initialValue);
And whenever the UI needs to respond to changing data:
setValue(newValue);
React takes care of updating the UI.
This is a major step forward from simply writing static components.
🎯 Final Summary
Today I learned:
What React State is
Why State is required
useStateState variables
State setter functions
Updating state
Functional state updates
Boolean state
Object state
Array state
State immutability
Props vs State
State + Props together
How state causes UI updates
Common mistakes
Best practices
React is starting to make much more sense now.
Props help components communicate.
State helps components remember and react to changes.
And together, they form the foundation of interactive React applications. 🚀
