React's useState Hook Fundamentals
Looking for a video tutorial about this? Watch our YouTube shorts explaining the useState hook,
Now in this post, we will be diving deeper into the concepts of useState. We will go through the steps to define a state, build a counter and use the functional updates too. So, let's get started!
Defining State
State is all the data shown in the component, so anything which will change in time or a value which is dynamic is called the state of that component.
Earlier in React, managing the state of a component was really hard using class components! 😅. With the introduction of hooks to React, useState hook allows us to easily manage the state/data related to a component with just a single line of code.
So, here is a basic syntax for defining state:
import { useState } from 'react';
function Component() {
const [score, setScore] = useState(0);
// ... other code
}
Break down
useState(0): Create a state by calling the hook and incrementing the value (here it is a number '0').score: This is our state variable. It has the current value.setScore: This is the setter function. Use this to update our state later.
We use array destructuring to grab these two pieces of data in a single line of code.
A Simple Counter
To understand the working of the useState hook, let's see it react to a user input. We will be building a classic Counter program which will increment a value when the user clicks a button. As simple as that!
So, here is how you build a simple counter component:
import { useState } from "react"
import { Button } from "@/components/ui/button"
export default function CounterUseState() {
const [count, setCount] = useState(0); // initialize the state
// function to increment the value
const handleIncrement = () => {
setCount(count + 1)
}
return (
<div>
<Button onClick={handleIncrement} className="counter-button">
Increment Value
</Button>
<div className="counter-display">Current State = {count}</div>
</div>
)
}
Whenever the user clicks the Increment Value button, the onClick handler fires setCount(count + 1). React sees that the state has changed, and it efficiently re-renders the component to display the updated number on the screen.
In the example shown above, we have used some extra styles. You can explore, edit or copy the code to all the examples. It is available in our GitHub repository.
Functional Updates
There is a hidden trap in the above code! The simple counter works great but if you try to update the state multiple times in quick succession (or asynchronously), you might run into stale data issues.
This is because setCount(count + 1) relies on the value of count at the time the render happened.
To guarantee you are always working with the absolute most recent state, you should use a functional update. Instead of passing a direct value to your setter function, you pass a callback function:
import React, { useState } from 'react';
export default function SafeCounter() {
const [count, setCount] = useState(0);
const handleIncrement = () => {
// We pass a function that takes the previous state as an argument
setCount(prevCount => prevCount + 1);
};
return (
<div>
<h2>Current Count: {count}</h2>
<button onClick={handleIncrement}>
Safe Increment
</button>
</div>
);
}
Why this is better?
By using prevCount => prevCount + 1, React guarantees that prevCount is the most up-to-date value, even if multiple state updates are called together. It is a best practice to adopt this pattern anytime your new state relies on your old state.
Conclusion
The useState hook is the first thing when creating interactive components in React. Just remember the following rules:
- Always use array destructuring to grab your state variable and setter.
- Never modify your state directly (always use the setter function!).
- Use functional updates (
prev => prev + 1) when your new state depends on the previous state.
Make sure you are subscribed to our YouTube channel ArtUs Academy.
Happy Coding!

