Back to all notes
Smart vs Dumb Components: A Practical Hierarchy for Features and UI
Keep feature logic in smart components and render with simple, reusable UI components.
Introduction
“Smart” components manage data and interactions; “dumb” components only render UI. This hierarchy lets you build complex features from simple visual building blocks.
Why this matters
Smart (feature) components handle data and interactions. Dumb (UI) components render the interface. This separation makes features composable and UI reusable.
The problem
Keeping state and markup together at the page level blurs concerns. There’s no clean split between behavior and UI, so reuse is limited.
Inefficient approach
Page-level components render feature UI directly:
import { useState } from "react";
function App() {
const [article, setArticle] = useState({
title: "Understanding React Patterns",
content: "React patterns help us write better, more maintainable code...",
likes: 0,
});
const handleLike = () => {
setArticle((prev) => ({ ...prev, likes: prev.likes + 1 }));
};
return (
<div>
<h1>Smart vs Dumb Components</h1>
<h2>Understanding React Patterns</h2>
<p>React patterns help us write better, more maintainable code...</p>
<button onClick={handleLike}>Like ({article.likes})</button>
</div>
);
}
export default App;
The solution
Create small, focused UI components and a smart feature component that orchestrates them.
import { useState } from "react";
function Card({ title, content }) {
return (
<div className="card">
<h2>{title}</h2>
<p>{content}</p>
</div>
);
}
function Button({ children, onClick }) {
return <button onClick={onClick}>{children}</button>;
}
function ArticleFeature() {
const [article, setArticle] = useState({
title: "Understanding React Patterns",
content: "React patterns help us write better, more maintainable code...",
likes: 0,
});
const handleLike = () => {
setArticle((prev) => ({ ...prev, likes: prev.likes + 1 }));
};
return (
<div>
<Card title={article.title} content={article.content} />
<Button onClick={handleLike}>Like ({article.likes})</Button>
</div>
);
}
function App() {
return (
<div>
<h1>Smart vs Dumb Components</h1>
<ArticleFeature />
</div>
);
}
export default App;
Step-by-step
- Create dumb UI components:
CardandButton. - Move feature state (
article) and handlers intoArticleFeature. - Compose UI: pass only the data UI needs (
title,content). - Wire actions: pass
handleLiketoButton. - Keep the page responsible only for placing the feature.
Why this is better
- UI components stay stateless and reusable.
- Feature components stay focused on behavior and orchestration.
- Pages compose features, which compose UI. Clean layers.
Tips
- Keep UI components pure and style‑focused; avoid side effects.
- If a UI component starts handling state, ask whether it’s becoming a feature.
- Extract repeated UI patterns early—it pays off quickly in larger apps.
Knowledge base
Problem snippet:
<h2>Understanding React Patterns</h2>
<button onClick={handleLike}>Like ({article.likes})</button>
Solution snippet:
<Card title={article.title} content={article.content} />
<Button onClick={handleLike}>Like ({article.likes})</Button>