🎨 Presentational vs. 🧩 Container Components in React
This distinction was popularized by Dan Abramov (one of Redux’s creators) as a way to separate how things look from how things work.
While modern React (hooks, functional components) has made the pattern less mandatory, the mindset is still extremely useful.
🎨 Presentational Components
Section titled “🎨 Presentational Components”Purpose: Focus on UI only — how things look.
Characteristics
Section titled “Characteristics”- Concerned with markup and styles.
- Receive all data via props.
- Rarely have their own state (unless it’s purely UI state like toggles or form field values).
- Don’t know where the data comes from.
- Usually functional components (but could be class-based in older code).
- Often reusable and easy to test.
Example
Section titled “Example”const UserCard = ({ name, email, onSelect }) => ( <div className="card" onClick={onSelect}> <h2>{name}</h2> <p>{email}</p> </div>);This component doesn’t fetch data, doesn’t manage global state — it just renders UI.
🧩 Container Components
Section titled “🧩 Container Components”Purpose: Handle logic, data, and behavior — how things work.
Characteristics
Section titled “Characteristics”- Manage data fetching.
- Manage state, reducers, or business logic.
- Pass data to presentational components.
- Handle events and transform/update data.
- Often used to glue UI to external data sources like APIs or global stores.
Example
Section titled “Example”const UserCardContainer = () => { const [user, setUser] = useState(null);
useEffect(() => { fetch("/api/user/1") .then(res => res.json()) .then(data => setUser(data)); }, []);
if (!user) return <p>Loading...</p>;
return ( <UserCard name={user.name} email={user.email} onSelect={() => console.log("Selected user:", user.id)} /> );};The container loads data and supplies it to the UI.
🧠 Quick Comparison Table
Section titled “🧠 Quick Comparison Table”| Aspect | Presentational | Container |
|---|---|---|
| Primary concern | UI | Logic/Data |
| Knows data source? | ❌ No | ✔️ Yes |
| Handles state? | Rarely | Frequently |
| Reusable? | Highly | Less so |
| Receives props? | ✔️ | ✔️ Often passes props |
| Typical contents | JSX, CSS | Fetch/axios, state hooks, business logic |
🕰️ Modern React Note (Hooks Era)
Section titled “🕰️ Modern React Note (Hooks Era)”While this pattern is still helpful conceptually, hooks blurred the line:
- A single component often includes UI + logic.
- Custom hooks now act like the modern equivalent of “containers,” encapsulating logic separately from UI.
For example:
const useUser = () => { const [user, setUser] = useState(null);
useEffect(() => { fetch("/api/user/1") .then(res => res.json()) .then(data => setUser(data)); }, []);
return user;};
const UserCardContainer = () => { const user = useUser(); return user ? <UserCard {...user} /> : <p>Loading...</p>;};This keeps things clean: logic in hooks, UI in components.
✔️ Summary
Section titled “✔️ Summary”- Presentational = UI
- Container = Logic/Data
- Modern React often merges them, but the separation remains a powerful mental model.
- Custom hooks now handle most container-like jobs.