Overview
React hooks let you use state and other React features without writing a class. The useState
hook is the most basic hook for managing state in functional components.
Steps
- Import the useState hook:
import React, { useState } from "react";
- Define state variables with the useState hook:
function Counter() {
// Declare a state variable named "count" with initial value 0
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
- Using multiple state variables:
function UserForm() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
return (
<form>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name"
/>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<p>
Current input: {name}, {email}
</p>
</form>
);
}
- Using objects as state:
function UserForm() {
const [user, setUser] = useState({ name: "", email: "" });
const handleChange = (e) => {
setUser({
...user, // Keep existing state
[e.target.name]: e.target.value, // Update only what changed
});
};
return (
<form>
<input
name="name"
type="text"
value={user.name}
onChange={handleChange}
placeholder="Name"
/>
<input
name="email"
type="email"
value={user.email}
onChange={handleChange}
placeholder="Email"
/>
<p>
Current input: {user.name}, {user.email}
</p>
</form>
);
}
Common Issues
- Forgetting the spread operator: When updating object state, you need to include
...prevState
to avoid losing other properties - Direct state mutation: Never modify state directly; always use the setter function
- Asynchronous state updates: State updates may be batched for performance, so don’t rely on the state value right after setting it
- Infinite render loops: Don’t call setState in the main component body; use events or useEffect
Additional Notes
- The useState hook returns an array with two elements:
- The current state value
- A function to update that value
- You can use array destructuring to give these elements any names you want
- For complex state logic, consider using
useReducer
instead - State is preserved between renders unless the component is unmounted
- For side effects (like data fetching), use the
useEffect
hook instead