React useState Hook
Table of Contents + −
In the last lesson you learned about React State, so you know state is data a component remembers and can change. This lesson shows the hook that actually adds that state to a function component: useState.
🤔 Why do we need useState?
Here’s the pain. A plain variable inside a component does not work for changing data. Let’s see why.
- You make a normal variable like
let count = 0inside the component. - You change it on a click, say
count = count + 1. In plain JavaScript that’s correct. - But the screen does not update. React has no idea the value changed, so it never re-draws.
- On top of that, every time the component runs again, that variable resets back to
0. It forgets.
So a normal variable has two problems. It does not tell React to re-draw, and it does not stay around between renders. useState fixes both at once.
🧩 What is useState?
useState is a React hook that lets a function component hold a value that stays around and that updates the screen when it changes.
- A hook is just a special React function whose name starts with “use”. It plugs extra features into a component.
useStategives you two things: the current value, and a function to change that value.- When you change the value through that function, React re-runs the component and updates the screen. That’s the whole point.
Think of it like a small box with a label. You can read what’s in the box anytime, and there’s one proper way to put something new in it, which also rings a bell so React knows to repaint.
🔌 Importing useState
Before you can use it, you have to bring it in from the React library. It does not exist on its own.
This line at the top of your file gives you access to the hook.
import { useState } from "react";The curly braces matter here. useState is a named export from React, so you pull it out by name inside { }.
🛠️ The syntax: value and setter
Now the line you’ll write over and over. This is how you create a piece of state.
const [count, setCount] = useState(0);Let’s read it from right to left, because that makes it click.
useState(0)creates the state and sets the starting value to0. That0is the initial value.- It hands you back a pair of things in an array: the current value, then a function to change it.
const [count, setCount] = ...is array destructuring. It pulls the first item intocountand the second intosetCount.- So now
countholds the value, andsetCountis the function you call to update it.
The names are up to you, but the convention is something and setSomething. So [user, setUser], [isOpen, setIsOpen], and so on. Stick to that and your code reads clearly.
Why an array, not an object?
useState returns an array on purpose. With an array you can name both items
whatever you like in one short line. That’s why you can call them count and
setCount instead of fixed names.
📺 Reading the value in JSX
Once you have the value, showing it on screen is easy. You just drop it into your JSX with curly braces.
This component reads count and displays it inside a paragraph.
import { useState } from "react";
function Counter() { const [count, setCount] = useState(0);
return <p>You clicked {count} times</p>;}Here’s what that {count} is doing for you.
- The
{count}part tells React to print the current value right there. - Since the starting value is
0, the screen first shows “You clicked 0 times”. - When
countchanges later, this text updates by itself.
🔄 Updating with the setter
So how do you change the value? You call the setter function. Never touch the variable directly.
Here we add a button. Clicking it calls setCount with the new value.
import { useState } from "react";
function Counter() { const [count, setCount] = useState(0);
return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> </div> );}Let’s walk through what happens on a click.
onClick={() => setCount(count + 1)}says: when the button is clicked, runsetCountwithcount + 1.setCountupdates the stored value and tells React the state changed.- React re-runs the
Counterfunction, socountnow reads the new number. - The
{count}in the JSX shows the new value. The screen updates on its own.
That’s a full working counter. Click the button and the number goes up every time.
🚫 Why not just count = count + 1?
This is the part beginners get wrong, so let’s be clear about it. You must use the setter, not a plain assignment.
// ❌ Wrong - React never finds out, the screen stays frozencount = count + 1;
// ✅ Right - the setter updates the value AND triggers a re-rendersetCount(count + 1);The difference is who gets told.
- A plain
count = count + 1changes a value in memory but says nothing to React. So React never re-renders and the screen is stuck. setCount(...)does two jobs at once. It saves the new value, and it asks React to re-run the component and repaint the screen.
So the setter is not extra typing for no reason. It’s the signal that wakes React up.
Always go through the setter
Changing a state variable directly does nothing useful. The UI will not update. Any time you want new state, call its setter function.
📍 Call hooks at the top level
One quick rule to keep in your pocket. Hooks like useState have to be called at the top level of your component.
- Put your
useStatecalls right at the start of the component function. - Do not call them inside an
if, inside a loop, or inside another function. - This lets React match each piece of state to the same hook on every render.
function Counter() { // ✅ Right - at the top level of the component const [count, setCount] = useState(0);
// ❌ Wrong - never put a hook inside a condition // if (count > 0) { // const [extra, setExtra] = useState(0); // }
return <p>{count}</p>;}We’ll go deeper into the hook rules in a later lesson. For now, just keep your hooks at the top and you’ll be fine.
🧩 What You’ve Learned
- ✅ A normal variable can’t drive the UI, because it doesn’t re-render and it resets each time
- ✅
useStateadds state that stays around and updates the screen when it changes - ✅ You import it with
import { useState } from "react" - ✅
const [count, setCount] = useState(0)gives you the current value plus a setter, with0as the initial value - ✅ You read the value in JSX with
{count} - ✅ You update it by calling the setter, like
setCount(count + 1) - ✅ Use the setter, not
count = count + 1, so React knows to re-render - ✅ Call hooks at the top level of the component, not inside ifs or loops
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does useState return?
Why: useState returns an array with two items: the current value and a setter function. You usually destructure them, like const [count, setCount] = useState(0).
- 2
In const [count, setCount] = useState(10), what is the 10?
Why: The argument you pass to useState is the initial value. So count starts at 10 on the first render.
- 3
Why should you call setCount instead of writing count = count + 1?
Why: A plain assignment changes a value but never notifies React, so the screen stays frozen. The setter updates the value and triggers a re-render.
- 4
Where should you call a hook like useState?
Why: Hooks must be called at the top level of the component so React can match each piece of state to the same hook on every render.
🚀 What’s Next?
Now you can create state, read it, and update it with the setter. Next you’ll learn the right way to update state, including why you sometimes pass a function to the setter and how to update state that depends on the previous value.