🤔What is useState in React?
So you've just started learning React or may you just made React frontend using AI and you keep seeing this useState thing everywhere. You started thinking, What the hell is it? Why is it everywhere in my project? So, don't worry we are going to figure this out in dev post.
🧠 First, what is "state"?
Think of state as your component's memory.
A regular JavaScript variable forgets its value every time a component re-renders. State remembers it. That's the whole idea.
// 👎This won't work
let count: number = 0;
count = count + 1;
// 👍This will work
const [count, setCount] = useState<number>(0);
😮The basic syntax
const [state, setState] = useState<Type>(initialState);
- value → the current state value
- setValue → the function you call to update it
- initialValue → what it starts as (a number, string, boolean, array, object — anything!)
- Type → the TypeScript type of your state (often inferred automatically!)
TypeScript can usually infer the type from the initial value, so useState(0) is the same as useState(0). But being explicit is great practice, especially for complex types.
Example 1: Counter
The classic. Let's build a simple counter.
import useState from "react";
function Counter(){
const [count, stateCount] = useState<number>(0);
function handleClick(){
setCount(count + 1);
}
return(
<div>
<p> You click me {count} times </p>
<button onClick={handleClick}> Click me </button>
</div>
);
}
export default Counter;
Every time you click the button, setCount updates the value and React re-renders the component with the new count. Simple!
Example 2: Toggle
Toggles are everywhere — dark mode, show/hide menus, open/close modals. Here's the pattern:
import { useState } from "react";
function DarkModeToggle() {
const [isDark, setIsDark] = useState<boolean>(false);
return (
<div style={{ background: isDark ? "#111" : "#fff", padding: "20px" }}>
<p style={{ color: isDark ? "#fff" : "#111" }}>
{isDark ? "Dark mode 🌙" : "Light mode ☀️"}
</p>
<button onClick={() => setIsDark(!isDark)}>Toggle</button>
</div>
);
}
export default DarkModeToggle;
The trick is !isDark — it just flips the boolean each time.
Example 3: Form Input
This one's super common. You want to capture what the user types:
import { useState, ChangeEvent } from "react";
function NameForm() {
const [name, setName] = useState<string>("");
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setName(e.target.value);
};
return (
<div>
<input
type="text"
placeholder="Enter your name"
value={name}
onChange={handleChange}
/>
<p>Hello, {name || "stranger"}! 👋</p>
</div>
);
}
export default NameForm;
A few things to notice:
value={name} keeps the input in sync with state (this is called a controlled input
)ChangeEvent is the TypeScript type for an input's change event — it tells TS exactly what e looks like
e.target.value is the current text in the input
3 Things to Remember
- Never mutate state directly
// ❌ Don't do this
count = count + 1;
// ✅ Do this
setCount(count + 1);
State updates trigger a re-render
Every time you call your setter function, React re-renders that component. That's how your UI stays up to date.Each component gets its own state
If you use twice on a page, each one has its own independent count. They don't share state.Be explicit with types when state can be null
// If the initial value could be null, tell TypeScript!
const [user, setUser] = useState<string | null>(null);
This is where TypeScript really earns its keep — it'll warn you if you try to use user without checking if it's null first.
👋That's it!
useState is honestly one of those things that clicks really fast once you start using it. The key insight is: whenever your UI needs to change based on user interaction, you probably need state.
Start with these three patterns — counter, toggle, form — and you'll have a solid foundation for almost everything. And with TypeScript in the mix, you'll catch bugs before they even happen.
Goodbye Imposter Syndrome!
Top comments (0)