What are "Smart" and "Dumb" components?
The essence of the pattern
The Container-Presentational Pattern splits components into two types:
| Type | Purpose |
|---|---|
| Container | Responsible for logic, data, and state |
| Presentational | Responsible only for rendering the UI |
The idea: "the container thinks, the presentational one shows"
Example
Presentational Component
It receives data through props and just displays it.
function UserCard({ name, age }) {
return (
<div className="card">
<h2>{name}</h2>
<p>Age: {age}</p>
</div>
);
}No state No requests Doesn't know where the data came from -> a pure UI component
Container Component
It manages state and logic, and passes data down.
function UserCardContainer() {
const [user, setUser] = useState(null);
useEffect(() => {
fetch('/api/user')
.then(res => res.json())
.then(data => setUser(data));
}, []);
if (!user) return <p>Loading...</p>;
return <UserCard name={user.name} age={user.age} />;
}Fetches data Manages state Triggers side effects Passes data to the presentational component
Why this is needed
| Problem | Solution via the pattern |
|---|---|
| Logic and UI mixed in one component -> hard to read | Split it: one thinks, the other shows |
| Hard to test and reuse | Presentational components are easy to test and reuse |
| Need to render the same UI with different data sources | You can use one Presentational with different Containers |
| A redesign breaks the logic | The UI can be replaced without touching the business logic |
Architecturally
Container (logic)
└── Presentational (UI)For example:
UserListContainer
└── UserList
└── UserCardTypical traits
| Trait | Container | Presentational |
|---|---|---|
| Holds state | Yes | No |
Uses hooks (useState, useEffect) | Yes | Rarely |
| Makes API requests | Yes | No |
| Knows about business logic | Yes | No |
| Accepts props for display | Yes | Yes |
| Defines markup and styles | No | Yes |
Example in a modern architecture (React + Redux)
// Presentational.jsx
export function TodoList({ todos, onToggle }) {
return (
<ul>
{todos.map(todo => (
<li
key={todo.id}
onClick={() => onToggle(todo.id)}
style={{ textDecoration: todo.done ? 'line-through' : 'none' }}
>
{todo.text}
</li>
))}
</ul>
);
}// Container.jsx
import { useSelector, useDispatch } from 'react-redux';
import { toggleTodo } from '../store/todoSlice';
import { TodoList } from './Presentational';
export function TodoListContainer() {
const todos = useSelector(state => state.todos);
const dispatch = useDispatch();
return (
<TodoList
todos={todos}
onToggle={(id) => dispatch(toggleTodo(id))}
/>
);
}In modern React
Although the pattern comes from the era of class components, it is still relevant, just implemented through hooks and composition.
Nowadays, the "container" can be:
- a hook (
useUser,useTodos) - a wrapper component
- a context provider
Summary
| What | Description |
|---|---|
| Idea | Split "logic" from "display" |
| Container | Fetches and processes data |
| Presentational | Displays the interface |
| Benefit | Reusability, readability, testability |
| Modern analog | Hooks + Dumb/UI components |
Bottom-line formula:
Containerknows what to show,Presentationalknows how to show it.
The "Smart" and "Dumb" component concepts (smart and dumb) are a more informal, but very popular, version of the "Container-Presentational" pattern you just asked about.
Let's break it down step by step.
The essence of the idea
React applications consist of two types of components:
| Component type | What it does |
|---|---|
| Smart | Manages logic, state, requests, and data |
| Dumb | Only responsible for display (UI), doesn't "think" |
"Smart thinks, Dumb shows."
Example
Dumb Component (presentational)
Just receives data and renders it.
function UserCard({ name, age }) {
return (
<div className="card">
<h2>{name}</h2>
<p>Age: {age}</p>
</div>
);
}Features:
- Has no state (
useState,useEffect) - Doesn't know where the data came from
- Easy to test and reuse
- Depends only on
props
Smart Component (container)
Responsible for the business logic and data.
function UserContainer() {
const [user, setUser] = useState(null);
useEffect(() => {
fetch('/api/user')
.then(res => res.json())
.then(data => setUser(data));
}, []);
if (!user) return <p>Loading...</p>;
return <UserCard name={user.name} age={user.age} />;
}Features:
- Manages state and logic
- Makes API requests
- Handles events
- Passes data down via props
Differences, in a table
| Characteristic | Smart component | Dumb component |
|---|---|---|
| Manages state | Yes | No |
| Makes requests | Yes | No |
| Knows the business logic | Yes | No |
| Renders UI | Partly | Mainly |
| Accepts props | Yes | Yes |
| Reusable | Not always | Easily |
| Testable | Harder | Simple |
| Examples | Containers, Hooks, Providers | Buttons, Cards, Modals |
The relationship between them
Smart
└── Dumb
└── (even smaller Dumb components)The smart component controls the data flow, while the "dumb" ones are responsible for pure UI.
Why this is convenient
Cleaner code: logic isn't mixed with markup Easier to test UI separately UI components become reusable The design can change without changing the logic The same Dumb components can be used in different parts of the app
Modern evolution
Today in React (especially with hooks and Next.js 13+), this pattern is often implemented not literally as "Smart/Dumb components", but through a split into:
- Hooks (smart) -
useUser(),useTodos(),useCart() - UI components (dumb) -
UserCard,TodoList,CartItem
Example:
// useUser.js
export function useUser() {
const [user, setUser] = useState(null);
useEffect(() => {
fetch('/api/user')
.then(r => r.json())
.then(setUser);
}, []);
return user;
}
// UserCard.jsx
export function UserCard({ user }) {
return (
<div>{user?.name ?? 'Loading...'}</div>
);
}
// Page.jsx
import { useUser } from './useUser';
import { UserCard } from './UserCard';
export default function Page() {
const user = useUser();
return <UserCard user={user} />;
}Now the "brains" live in the hook, and the "dumbness" in the UI component. This is the modern way to implement the same pattern.
Summary
| Concept | What it means |
|---|---|
| Smart Component | A component that manages logic, state, and data |
| Dumb Component | A component that just displays UI based on props |
| The pattern solves | Separation of concerns and improved architecture |
| Modern analog | Hooks + UI components |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.