React’s state model is one of its most influential ideas. Instead of manually updating the DOM, developers update state, and React handles the rest. This article explores how state works, why it’s essential, and how to manage it using modern React patterns.
What Is State in React?
State is mutable data that a component controls. When state changes, React re-renders the component to reflect the new information.
State is ideal for representing:
- User input
- UI visibility toggles
- Form data
- Counters, timers, and dynamic values
Unlike props, which flow from parent to child, state is owned by the component itself.
The useState Hook: The Foundation of Local State
useState is the simplest and most common way to manage state in function components.
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Current count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increase</button>
</div>
);
}
What This Demonstrates
countis the current state value.setCountupdates the state.- Updating state triggers a re-render.
- React ensures the UI stays consistent with the data.
Rules of State You Should Know
- State updates are asynchronous React batches updates for performance.
- State should be treated as immutable Always create new values instead of mutating existing ones.
- State is isolated per component Each component manages its own data unless shared intentionally.
- Derived state should be minimized Compute values when needed instead of storing duplicates.
These principles help maintain predictable behavior as applications grow.
When useState Isn’t Enough: Introducing useReducer
For more complex state logic—especially when updates depend on previous state or involve multiple actions—useReducer provides structure.
import { useReducer } from "react";
function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
);
}
Why useReducer Matters
- Centralized logic All updates flow through a single reducer.
- Predictable transitions Each action describes a clear state change.
- Scales well Ideal for forms, complex UI flows, or multi-step interactions.
State vs. Props: A Quick Comparison
| Concept | Description | When to Use |
| State | Mutable data controlled by the component | When the component needs to track changes |
| Props | Read-only data passed from parent | When passing information down the tree |
| Derived values | Computed from state or props | When the value can be calculated on the fly |
Why State Matters
State transforms components from static renderers into dynamic systems. It enables:
- Interactivity
- Real-time updates
- User-driven behavior
- Complex UI flows
Mastering state is essential for building robust, scalable React applications.
Sources & Further Reading
- React State Overview:
https://react.dev/learn/state-a-components-memory(react.dev in Bing) - useState Documentation:
https://react.dev/reference/react/useState(react.dev in Bing) - useReducer Documentation:
https://react.dev/reference/react/useReducer(react.dev in Bing)

