In React, state is an object that allows you to store and manage dynamic data within a component. Unlike props, which are passed from parent to child, the state is owned and managed locally by the component itself.
1. What Is State?
- State represents the internal data of a component that can change over time.
- When the state changes, React triggers a re-render of the component to update the UI.
- State is only available in components that use React Hooks (e.g.,
useState
) or are class components.
2. State in Functional Components
Since React 16.8, functional components can use the useState
Hook to manage state.
Basic Example: Using useState
import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); } export default Counter;
useState(0)
initializes the state variablecount
with the value0
.setCount
is used to update the state.
3. State in Class Components
Class components use the this.state
object to manage state and this.setState()
to update it.
Example: State in a Class Component
import React, { Component } from 'react'; class Counter extends Component { constructor(props) { super(props); this.state = { count: 0 }; } increment = () => { this.setState({ count: this.state.count + 1 }); }; render() { return ( <div> <p>Count: {this.state.count}</p> <button onClick={this.increment}>Increment</button> </div> ); } } export default Counter;
4. Updating State
- Functional Components: Use the setter function provided by
useState
.const [state, setState] = useState(initialValue); setState(newValue);
- Class Components: Use
this.setState()
to update the state.this.setState({ key: newValue });
5. State with Objects
React state can store objects, arrays, or other data types.
Example: Object State
import React, { useState } from 'react'; function UserProfile() { const [user, setUser] = useState({ name: 'John', age: 25 }); const updateAge = () => { setUser({ ...user, age: user.age + 1 }); // Use the spread operator to retain existing state }; return ( <div> <p>Name: {user.name}</p> <p>Age: {user.age}</p> <button onClick={updateAge}>Increase Age</button> </div> ); } export default UserProfile;
6. State with Arrays
Example: Managing Array State
import React, { useState } from 'react'; function TodoList() { const [todos, setTodos] = useState(['Learn React', 'Build a project']); const addTodo = () => { setTodos([...todos, 'Practice daily']); // Add a new item to the array }; return ( <div> <ul> {todos.map((todo, index) => ( <li key={index}>{todo}</li> ))} </ul> <button onClick={addTodo}>Add Todo</button> </div> ); } export default TodoList;
7. State Is Asynchronous
State updates in React are asynchronous. If you need to perform actions based on the updated state, use a callback.
Example: Using Previous State
import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); const increment = () => { setCount((prevCount) => prevCount + 1); // Use the previous state }; return ( <div> <p>Count: {count}</p> <button onClick={increment}>Increment</button> </div> ); } export default Counter;
8. State and Lifecycle
In class components, state is closely tied to lifecycle methods such as componentDidMount
, componentDidUpdate
, and componentWillUnmount
. In functional components, the useEffect
Hook handles side effects and lifecycle-like behavior.
Example: State and useEffect
import React, { useState, useEffect } from 'react'; function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const interval = setInterval(() => { setSeconds((prev) => prev + 1); }, 1000); return () => clearInterval(interval); // Cleanup the interval }, []); return <p>Timer: {seconds} seconds</p>; } export default Timer;
9. State Best Practices
- Keep State Localized: Only keep state in the components that need it.
- Avoid Direct Mutations: Never modify the state directly—always use the setter function or
this.setState()
. - Use Functional Updates: When the new state depends on the previous state, use a functional update.
- Group Related State: Use a single object for related data instead of multiple state variables.
- Avoid Overuse of State: If data doesn’t change, prefer props over state.
10. Example: Complete State Management
import React, { useState } from 'react'; function App() { const [tasks, setTasks] = useState(['Learn React', 'Build a project']); const [newTask, setNewTask] = useState(''); const addTask = () => { if (newTask.trim()) { setTasks([...tasks, newTask]); setNewTask(''); } }; return ( <div> <h1>Task Manager</h1> <ul> {tasks.map((task, index) => ( <li key={index}>{task}</li> ))} </ul> <input type="text" value={newTask} onChange={(e) => setNewTask(e.target.value)} /> <button onClick={addTask}>Add Task</button> </div> ); } export default App;
11. State vs Props
Feature | State | Props |
---|---|---|
Mutability | Mutable (can be changed) | Immutable (read-only) |
Ownership | Managed within the component | Passed from parent to child |
Usage | For dynamic and interactive data | For configuration and static data |
Update Mechanism | Updated using useState or setState |
Cannot be updated by the component |
Conclusion
State is a core concept in React that allows components to be dynamic and interactive.