π³ Component Purity: The Kitchen That Never Gets Messy
The Magic Recipe Machine
Imagine you have a magical recipe machine in your kitchen. You put in flour, eggs, and sugar β and it ALWAYS gives you the same delicious cake. No surprises. No explosions. No mess on the walls.
Thatβs what a pure component is in React!
π― What is a Pure Component?
A pure component is like a perfect robot chef:
- Same ingredients = Same dish (always!)
- Never sneaks into the fridge while cooking
- Doesnβt change anything in the kitchen
// π’ PURE: Same input = Same output
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
// Give it "Emma" β Always shows "Hello, Emma!"
// Give it "Liam" β Always shows "Hello, Liam!"
The Golden Rule
A pure function does ONE thing: takes input, returns output. Nothing else!
graph TD A["Props Input"] --> B["Pure Component"] B --> C["Same JSX Output"] A2["Same Props"] --> B B --> C2["Identical Result!"]
β οΈ Side Effects: The Kitchen Saboteurs
Whatβs a Side Effect?
A side effect is when your robot chef does sneaky things while cooking:
- π± Makes a phone call
- πͺ Opens the refrigerator
- π Writes on the shopping list
- β° Checks what time it is
These arenβt bad things! But they shouldnβt happen while cooking (rendering).
π΄ Bad: Side Effects INSIDE Render
// β IMPURE: Doing sneaky things while rendering!
function BadCounter({ count }) {
// Side effect: Changing something outside!
document.title = `Count: ${count}`;
// Side effect: Making network request!
fetch('/api/log', { method: 'POST' });
return <p>Count is {count}</p>;
}
Why is this bad?
- React might render your component many times
- Each render triggers those side effects again and again
- Your title changes unexpectedly
- You send 10 network requests instead of 1!
π’ Good: Side Effects in useEffect
// β
PURE: Render just returns JSX
function GoodCounter({ count }) {
// Side effects go in useEffect (after render)
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
return <p>Count is {count}</p>;
}
π§Ή Keeping Components Pure
The Three Promises of Purity
| Promise | Meaning | Example |
|---|---|---|
| π― Predictable | Same props = Same result | Greeting({name: "Jo"}) always shows βHello, Jo!β |
| π« No Mutations | Never change props or outside variables | Donβt modify arrays or objects passed in |
| π No Side Effects | Donβt talk to the outside world during render | No fetch, no localStorage, no DOM changes |
Common Purity Mistakes
β Mutating Props
// BAD: Changing the prop directly!
function BadList({ items }) {
items.push("sneaky item"); // NO!
return <ul>{items.map(i => <li>{i}</li>)}</ul>;
}
β Create New Data Instead
// GOOD: Make a new array
function GoodList({ items }) {
const allItems = [...items, "new item"];
return <ul>{allItems.map(i => <li>{i}</li>)}</ul>;
}
β Reading Changing Values
// BAD: Reading random/time during render
function BadClock() {
const now = new Date(); // Different every time!
return <p>{now.toLocaleTimeString()}</p>;
}
β Pass Values as Props
// GOOD: Time comes from outside
function GoodClock({ time }) {
return <p>{time.toLocaleTimeString()}</p>;
}
π PureComponent Class
The Automatic Optimizer
Before React hooks, we had class components. PureComponent was like giving your robot chef a memory:
βHey, I already made this exact cake 5 minutes ago. Same ingredients. Iβll just serve the one I made before!β
import { PureComponent } from 'react';
class OptimizedGreeting extends PureComponent {
render() {
console.log('Rendering...');
return <h1>Hello, {this.props.name}!</h1>;
}
}
How It Works
graph TD A["New Props Arrive"] --> B{Same as before?} B -->|Yes| C["Skip Render! π"] B -->|No| D["Render Component"] D --> E["Show Updated UI"]
PureComponent Does Shallow Comparison
| What it compares | How |
|---|---|
| Strings, Numbers | "hello" === "hello" β
|
| Objects | Same reference? obj1 === obj2 |
| Arrays | Same reference? arr1 === arr2 |
β οΈ Important! Shallow means it only checks the βaddressβ of objects, not their contents.
// These look the same but are DIFFERENT to PureComponent
const user1 = { name: "Jo" };
const user2 = { name: "Jo" };
user1 === user2 // false! Different objects
Modern Equivalent: React.memo
Today, we use React.memo for function components:
import { memo } from 'react';
// Same optimization, modern style!
const OptimizedGreeting = memo(function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
});
π¬ Quick Story Recap
| Concept | Kitchen Analogy |
|---|---|
| Pure Component | Robot chef that always makes the same dish from the same ingredients |
| Side Effect | Sneaky actions (phone calls, checking fridge) during cooking |
| Side Effects in Render | Making phone calls while whisking eggs β chaos! |
| useEffect | βAfter you finish cooking, THEN make the phone callβ |
| PureComponent | Chef with memory: βI made this before, hereβs your cake!β |
| React.memo | Modern version of the memory chef |
π‘ Remember This!
βββββββββββββββββββββββββββββββββββββββ
β PURE COMPONENT = PREDICTABLE β
β βββββββββββββββββββββββββββββββββ β
β β Same input β Same output β
β β No side effects during render β
β β Never mutate props or state β
β β Use useEffect for side effects β
βββββββββββββββββββββββββββββββββββββββ
Youβve got this! π Keep your components pure, and your React app will be fast, predictable, and bug-free!
