The useState
Hook is one of the fundamental Hooks in React, allowing you to add state management to functional components. Before Hooks, state was only available in class components, but with useState
, you can now manage state in functional components as well.
In React, components are designed to be reusable and dynamic, often needing to respond to user input, track interaction states, or manage data over time. However, functional components alone are stateless, meaning they don’t inherently remember past user interactions or changes. This is where useState
comes in—it enables functional components to “remember” information between renders, thus making them stateful.
Here are a few reasons why useState
is essential:
Interactivity: React apps are often interactive, requiring components to respond to user actions like clicks, typing, or form submissions. useState
allows you to manage and track changes in data or UI based on these interactions.
Component Reusability: useState
helps make components more modular and reusable. Different instances of the same component can have their own independent state, making it easier to manage complex UIs
How useState Works
Importing useState
: To use useState
, you first need to import it from React:
import React, { useState } from 'react';
Declaring State: When you call useState
, you pass the initial state as an argument. The Hook returns an array with two elements:
- The current state value.
- A function to update that state.
Here’s an example of using useState
to manage a counter:
function Counter() {
const [count, setCount] = useState(0); // Initialize state with 0
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Updating State: You update the state by calling the state updater function (setCount
in this case). The new state value you pass to this function replaces the old one.
setCount(count + 1);
Every time you call this function, React re-renders the component with the new state value.
Multiple State Variables: You can call useState
multiple times in the same component to manage multiple state variables:
function Form() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
// Handle form submission or other logic here
return (
<form>
<input value={name} onChange={(e) => setName(e.target.value)} />
<input value={email} onChange={(e) => setEmail(e.target.value)} />
</form>
);
}
What can state hold
The state can hold various types of data, which can be used to control the rendering of the component and its behavior. The data held in the state can be primitive data types like strings and numbers, as well as more complex data structures like arrays and objects.
const [count, setCount] = useState(0);
const [username, setUsername] = useState('Guest');
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [todos, setTodos] = useState(["John", "Smith", "Sarah"]);//array
const [todos, setTodos] = useState([100, 230, 300]);//array
const [profile, setProfile] = useState({ name: '', email: '', age: 0 });//object
const [userList, setUserList] = useState([
{ name: 'John', email: 'john@email.com', age: 30 },
{ name: 'Jane', email: 'jane@email.com', age: 25 },
{ name: 'Doe', email: 'doe@email.com', age: 28 }
]);//array of objects
Example 1: Toggle feature
You might want to allow users to show or hide content, like a dropdown menu or a modal dialog.
function ToggleContent() {
const [isVisible, setIsVisible] = useState(false);
return (
<div>
<button onClick={() => setIsVisible(!isVisible)}>
{isVisible ? 'Hide' : 'Show'} Content
</button>
{isVisible && <p>This is the toggled content!</p>}
</div>
);
}
//The isVisible state controls whether the content is shown or hidden. When the user clicks the button, the state toggles, triggering the component to re-render with the updated visibility.
Example 2: Counter application
A simple example is a counter that increments or decrements based on user actions.
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increase</button>
<button onClick={() => setCount(count - 1)}>Decrease</button>
</div>
);
}
//The count state tracks the current value of the counter. Each time the user clicks a button, the state is updated, causing the component to re-render and display the new count.
Updating State that stores an object
setProfile({
...profile, // Spread the existing profile object
[name]: value // Update the specific field in the profile object
});
Updating state that stores an array
const [todos, setTodos] = useState([]); // Initializing the state to store an array of todo items
setTodos([...todos, "Learn React"]); // Updating the array by adding a new todo item
setTodos(["Learn React"]); // Cleaning the previous state and adding a single item "Learn React" to it
Updating state that stores an array of objects
const [users, setUsers] = useState([]); // Initializing the state to store an array
setUsers([
{ name: 'Alice', email: 'alice@email.com' },
{ name: 'Bob', email: 'bob@email.com' }
]);//fill the state with to new objects(user)
setUsers([...users, { name: 'kayvan', email: 'kayvan@email.com' }]); // Add the new user object to the array and keep also the previous ones. "...user" means keeping the previous value.