The useState
hook is one of the most commonly used hooks in React. It allows you to add and manage state in functional components, making your components dynamic and interactive.
Syntax
const [state, setState] = useState(initialValue);
- state: The current state value.
- setState: A function to update the state.
- initialValue: The initial value of the state (can be a number, string, boolean, array, object, etc.).
Basic Example
import React, { useState } from "react"; function Counter() { const [count, setCount] = useState(0); const increment = () => setCount(count + 1); const decrement = () => setCount(count - 1); return ( <div> <p>Count: {count}</p> <button onClick={increment}>Increment</button> <button onClick={decrement}>Decrement</button> </div> ); } export default Counter;
Updating State
- Direct Update:
- Use
setState
with the new value directly.setState(newValue);
Example:
setCount(count + 1);
- Use
- Functional Update:
- Use a function inside
setState
to calculate the new state based on the previous state.setState((prevState) => prevState + 1);
Example:
setCount((prevCount) => prevCount + 1);
Use this method when your new state depends on the previous state (e.g., in asynchronous updates).
- Use a function inside
Using useState
with Different Data Types
1. String
import React, { useState } from "react"; function Greeting() { const [name, setName] = useState(""); return ( <div> <input type="text" placeholder="Enter your name" value={name} onChange={(e) => setName(e.target.value)} /> <p>Hello, {name || "Stranger"}!</p> </div> ); } export default Greeting;
2. Array
import React, { useState } from "react"; function TodoList() { const [tasks, setTasks] = useState([]); const addTask = () => { setTasks([...tasks, `Task ${tasks.length + 1}`]); }; return ( <div> <button onClick={addTask}>Add Task</button> <ul> {tasks.map((task, index) => ( <li key={index}>{task}</li> ))} </ul> </div> ); } export default TodoList;
3. Object
import React, { useState } from "react"; function Profile() { const [user, setUser] = useState({ name: "", age: 0 }); const updateName = (e) => setUser({ ...user, name: e.target.value }); const updateAge = (e) => setUser({ ...user, age: e.target.value }); return ( <div> <input type="text" placeholder="Name" value={user.name} onChange={updateName} /> <input type="number" placeholder="Age" value={user.age} onChange={updateAge} /> <p> Hello, {user.name || "Stranger"}! You are {user.age || "unknown"} years old. </p> </div> ); } export default Profile;
Best Practices
- Initialize Properly:
- Always provide an appropriate initial state. For example, use an empty string for text,
0
for numbers, and[]
for arrays.
- Always provide an appropriate initial state. For example, use an empty string for text,
- Avoid Direct State Mutation:
- Never modify state directly. Always create a new state object or array to ensure React detects changes.
// Incorrect state.push(newValue); // Correct setState([...state, newValue]);
- Never modify state directly. Always create a new state object or array to ensure React detects changes.
- Use Functional Updates for Asynchronous Changes:
- When multiple updates occur in rapid succession, functional updates ensure the correct previous state is used.
- Group Related State:
- Use objects or arrays to group related state variables for better organization.