React State: Syntax, Usage, and Examples
React state allows components to store and manage dynamic data that influences their behavior and appearance. Unlike props, which are immutable, state can change over time in response to user interactions, API calls, or other events.
How to Use React State
Use React’s useState
hook to create and update state in functional components.
Declaring State with useState
The useState
hook initializes state and provides a function to update it.
jsx
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
useState(0)
sets the initial state to0
.setCount(count + 1)
updates the state when the button is clicked.
Updating State Based on Previous State
To ensure updates are based on the latest state, pass a function to the setter.
jsx
const [count, setCount] = useState(0);
const increase = () => {
setCount((prevCount) => prevCount + 1);
};
Using prevCount
prevents state updates from being overridden in asynchronous operations.
Handling Objects in State
State can store objects instead of just primitive values.
jsx
const [user, setUser] = useState({ name: "Alice", age: 25 });
const updateAge = () => {
setUser((prevUser) => ({ ...prevUser, age: prevUser.age + 1 }));
};
The spread operator (...prevUser
) preserves existing properties when updating only one.
When to Use React State
State is useful when a component needs to manage dynamic data.
Handling User Input
Forms store input values using state.
jsx
function TextInput() {
const [text, setText] = useState("");
return (
<input type="text" value={text} onChange={(e) => setText(e.target.value)} />
);
}
Toggling UI Elements
State enables components to switch between different views.
jsx
function Toggle() {
const [isVisible, setIsVisible] = useState(true);
return (
<div>
<button onClick={() => setIsVisible(!isVisible)}>Toggle</button>
{isVisible && <p>This is visible.</p>}
</div>
);
}
Tracking API Responses
Manage API data by updating state after fetching results.
jsx
function FetchData() {
const [data, setData] = useState(null);
useEffect(() => {
fetch("https://api.example.com/data")
.then((res) => res.json())
.then((result) => setData(result));
}, []);
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
Examples of React State
State is widely used in React applications. Here are some common examples.
Counter App
A simple counter that increases and decreases values.
jsx
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count - 1)}>-</button>
<span>{count}</span>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}
Dark Mode Toggle
Toggle between light and dark themes.
jsx
function ThemeToggle() {
const [darkMode, setDarkMode] = useState(false);
return (
<div style={{ background: darkMode ? "black" : "white", color: darkMode ? "white" : "black" }}>
<button onClick={() => setDarkMode(!darkMode)}>Toggle Theme</button>
</div>
);
}
Managing a List of Items
Add and remove items from a list using state.
jsx
function ItemList() {
const [items, setItems] = useState([]);
const addItem = () => {
setItems([...items, `Item ${items.length + 1}`]);
};
return (
<div>
<button onClick={addItem}>Add Item</button>
<ul>{items.map((item, index) => <li key={index}>{item}</li>)}</ul>
</div>
);
}
Learn More About React State
State vs. Context API
Using state inside a single component works well, but passing state to multiple components often leads to props drilling, where props are passed down through several layers.
React Context API helps manage global state without passing props manually.
jsx
const ThemeContext = React.createContext();
function ThemedComponent() {
const theme = React.useContext(ThemeContext);
return <div style={{ background: theme }}>Themed Content</div>;
}
function App() {
return (
<ThemeContext.Provider value="lightgray">
<ThemedComponent />
</ThemeContext.Provider>
);
}
Managing Global State in React
For complex applications, React’s built-in state management may not be enough. Use third-party libraries like Redux, Zustand, or Recoil for handling global state.
Example using Redux:
jsx
import { createStore } from "redux";
const reducer = (state = { count: 0 }, action) => {
switch (action.type) {
case "INCREMENT":
return { count: state.count + 1 };
default:
return state;
}
};
const store = createStore(reducer);
This centralizes state and makes updates predictable.
setState in Class Components
Before React hooks, class components used setState
for state management.
jsx
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState((prevState) => ({ count: prevState.count + 1 }));
};
render() {
return <button onClick={this.increment}>{this.state.count}</button>;
}
}
Though functional components with hooks are now the standard, understanding class-based state management helps with maintaining older React applications.
Looking to dive deeper into React state and other essential React concepts? Check out our React course.