Foundation - Understanding the Zombie Metaphor
Learn why the zombie metaphor helps organize React code and how to distinguish between UI components (zombies) and logic components (brains).
Learning Objectives
By the end of this module, you will be able to:
- Understand why the zombie metaphor helps organize React code
- Distinguish between UI components (zombies) and logic components (brains)
- Recognize the mental model shift from traditional React patterns
Why Zombies?
When building React applications, one of the biggest challenges is keeping code organized and maintainable. Traditional React patterns often mix presentation logic with business logic, making it difficult to:
- Find where data transformations happen
- Understand component responsibilities
- Test components in isolation
- Refactor without breaking unrelated features
The Dead Simple Discipline introduces a simple mental model: zombies (UI) and brains (logic). This metaphor helps us separate concerns and build more maintainable applications.
The Core Metaphor
Green = UI (Skin) → Pure render, props-in/markup-out
Pink = Logic (Brains) → State, rules, effects, orchestration
🟢 Zombies (UI Components)
Zombies are pure presentation components. They:
- Take props and render markup
- Have no internal state (unless purely presentational)
- Don’t make API calls
- Don’t contain business logic
- Are predictable and easy to test
Think of zombies as the “skin” — they display information but don’t think or make decisions.
🧠 Brains (Logic Components)
Brains handle all the thinking:
- Manage state
- Execute business rules
- Orchestrate API calls
- Handle side effects
- Coordinate between multiple zombies
Think of brains as the “nervous system” — they process information and make decisions.
Simple Analogies
Restaurant Analogy
Imagine a restaurant:
- Waiters (Zombies): They take orders and serve food. They don’t decide what’s on the menu or how to cook. They simply present what the kitchen gives them.
- Chefs (Brains): They decide recipes, orchestrate cooking, manage inventory, and coordinate timing. They think and make decisions.
In React terms:
- A
CustomerCardcomponent (zombie) displays customer information - A
useCustomerDatahook (brain) fetches and processes customer data - The zombie receives data as props and renders it — no thinking required
Body Analogy
Think of your application like a body:
- Skin (Zombies): Visible, displays information, responds to touch
- Nervous System (Brains): Processes signals, makes decisions, coordinates responses
The skin doesn’t decide when to sweat or shiver — the nervous system does. Similarly, UI components shouldn’t decide what data to fetch or how to transform it.
Interactive Exercise: Before and After
Let’s look at a component that mixes concerns:
// ❌ Bad: Mixed concerns
function CustomerProfile() {
const [customer, setCustomer] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/customers/123')
.then(res => res.json())
.then(data => {
setCustomer(data);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
return (
<div>
<h2>{customer.name}</h2>
<p>{customer.email}</p>
<button onClick={() => {
// Business logic mixed in!
if (customer.status === 'active') {
deactivateCustomer(customer.id);
}
}}>
Toggle Status
</button>
</div>
);
}
Now let’s separate it into zombies and brains:
// ✅ Good: Separated concerns
// Brain: Handles logic
function useCustomerProfile(customerId: string) {
const [customer, setCustomer] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`/api/customers/${customerId}`)
.then(res => res.json())
.then(data => {
setCustomer(data);
setLoading(false);
});
}, [customerId]);
const toggleStatus = () => {
if (customer?.status === 'active') {
deactivateCustomer(customer.id);
}
};
return { customer, loading, toggleStatus };
}
// Zombie: Pure presentation
function CustomerProfile({ customer, loading, onToggleStatus }) {
if (loading) return <div>Loading...</div>;
return (
<div>
<h2>{customer.name}</h2>
<p>{customer.email}</p>
<button onClick={onToggleStatus}>
Toggle Status
</button>
</div>
);
}
// Brain boundary: Connects brain to zombie
function CustomerProfileView({ customerId }) {
const { customer, loading, toggleStatus } = useCustomerProfile(customerId);
return (
<CustomerProfile
customer={customer}
loading={loading}
onToggleStatus={toggleStatus}
/>
);
}
Key Differences:
- The zombie (
CustomerProfile) is now pure — it just renders - The brain (
useCustomerProfile) handles all logic - The boundary component (
CustomerProfileView) connects them
Creative Application Task
Look at this code sample and identify which parts are zombies and which are brains:
function ProductList() {
const [products, setProducts] = useState([]);
const [filter, setFilter] = useState('all');
useEffect(() => {
fetch('/api/products')
.then(res => res.json())
.then(data => setProducts(data));
}, []);
const filteredProducts = products.filter(p => {
if (filter === 'all') return true;
return p.category === filter;
});
return (
<div>
<select value={filter} onChange={(e) => setFilter(e.target.value)}>
<option value="all">All</option>
<option value="electronics">Electronics</option>
<option value="clothing">Clothing</option>
</select>
<ul>
{filteredProducts.map(product => (
<li key={product.id}>
<h3>{product.name}</h3>
<p>{product.price}</p>
</li>
))}
</ul>
</div>
);
}
Questions to consider:
- What parts handle state and logic? (Brains)
- What parts are pure presentation? (Zombies)
- How would you separate this into zombies and brains?
Key Takeaways
- Zombies are pure UI components that receive props and render markup
- Brains handle state, business logic, and side effects
- Separating zombies from brains makes code more maintainable and testable
- The zombie metaphor provides a simple mental model for organizing React code
Next Steps
Now that you understand the foundation, you’re ready to learn the 8 rules that guide the Dead Simple Discipline. Continue to Rules Part 1 to learn about starting undead, maintaining the horde ratio, and the 3-click brain rule.