Understanding the difference between stateful and stateless components is fundamental to React development. Here’s a comprehensive comparison:
1. Stateless (Presentational) Components
Characteristics:
- No internal state (only use props)
- Also called “dumb” or “presentational” components
- Primary purpose is UI rendering
- Easier to test and reuse
Example:
// Functional component (stateless)
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
// Class component (stateless)
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
When to Use:
✔ Displaying static data
✔ Receiving data via props
✔ Pure UI rendering without logic
2. Stateful (Container) Components
Characteristics:
- Manage their own state (using
useState
orthis.state
) - Also called “smart” or “container” components
- Handle data fetching, state changes, and business logic
- Often contain stateless components as children
Example:
// Functional component (stateful with hooks)
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
// Class component (stateful)
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Increment
</button>
</div>
);
}
}
When to Use:
✔ Managing form data
✔ Handling user interactions
✔ Data fetching and state management
✔ Business logic implementation
3. Key Differences
Feature | Stateless Components | Stateful Components |
---|---|---|
State | No internal state | Has internal state |
Props | Receive data via props | May receive and manage props |
Complexity | Simple | More complex |
Reusability | Highly reusable | Less reusable |
Testing | Easier to test | Harder to test |
Lifecycle Methods | None (functional) or basic (class) | Full lifecycle access |
Performance | Generally better | Potential performance impact |
4. Best Practices
- Prefer stateless components when possible
- Separate concerns – Keep stateful logic in container components
- Lift state up when multiple components need access
- Use hooks (
useState
,useReducer
) in functional components - Consider context or state management for complex state
Pattern: Container/Presentational Components
// Container (stateful)
function UserContainer() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetchUsers().then(data => setUsers(data));
}, []);
return <UserList users={users} />;
}
// Presentational (stateless)
function UserList({ users }) {
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
5. Modern Approach with Hooks
With React Hooks, the line between stateful and stateless components has blurred:
- Any functional component can become stateful with
useState
- Custom hooks allow extracting stateful logic
// Custom hook for stateful logic
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = () => setCount(c => c + 1);
return { count, increment };
}
// Component using the hook
function Counter() {
const { count, increment } = useCounter();
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
6. When to Choose Which?
Use Case | Recommended Type |
---|---|
Simple UI rendering | Stateless |
Form handling | Stateful |
Data fetching | Stateful |
Reusable UI pieces | Stateless |
App-wide state management | Stateful + Context/Redux |
Key Takeaways
- Stateless components are pure functions of their props
- Stateful components manage state and behavior
- Modern React favors functional components with hooks
- The container/presentational pattern remains useful
- Most apps need a mix of both types