React doesn’t ask you to build pages—it asks you to build components. These self‑contained units let you compose interfaces the same way LEGO bricks snap together. As Hallie & Osmani put it, “Components are the building blocks of any React app.”
1 What exactly is a component?
A component is simply a JavaScript function (or ES6 class) that receives props and returns UI:
function Welcome({ name }) {
return <h1>Hello, {name}!</h1>;
}
That single Welcome
function is a valid React component because it accepts one argument (props
) and returns React elements. Components written as functions are called function components, while those written with classes are called class components. Today, hooks make function components the default choice, but you’ll still encounter both styles in large codebases.
Key roles of a component
- Encapsulate markup and behaviour.
- Accept arbitrary input via props and stay pure (render output is a function of props + state).
- Enable composition—your UI becomes a tree of nested components instead of a monolithic page.
2 Why (and when) to extract components
Even tiny apps grow into a forest of UI concerns. To keep things maintainable you’ll often “extract” sub‑components—peeling off reusable bits into their own files. Extraction pays off when:
- A piece of UI appears in multiple places (Button, Panel, Avatar).
- A section is complex enough to reason about separately (FeedStory, Comment).
The book’s example in brief
Imagine a chunky Tweet
component with avatar, name, handle, content, time‑stamp, and actions. Trying to tweak just the avatar logic would be painful because everything is tangled. The authors show how to carve it up into:
-
Avatar
– renders just the user’s image. -
User
– wrapsAvatar
and the display name. -
Tweet
– becomes mostly layout glue.
“This component can be a bit difficult to manipulate… But we can still extract a few components from it.”
Let’s recreate a simplified version.
// 1️⃣ Start: one large component
function Tweet({ user, message, time }) {
return (
<article className="tweet">
<img className="avatar" src={user.avatar} alt={user.name} />
<div>
<strong>{user.name}</strong> @{user.handle}
<p>{message}</p>
<span>{time}</span>
</div>
</article>
);
}
// 2️⃣ Extract: Avatar — small & focused
function Avatar({ user }) {
return <img className="avatar" src={user.avatar} alt={user.name} />;
}
// 3️⃣ Extract: User — composes Avatar + name/handle
function User({ user }) {
return (
<header className="user">
<Avatar user={user} />
<strong>{user.name}</strong> @{user.handle}
</header>
);
}
// 4️⃣ Final: lean Tweet component
function Tweet({ user, message, time }) {
return (
<article className="tweet">
<User user={user} />
<p>{message}</p>
<footer>{time}</footer>
</article>
);
}
Benefits we unlocked
-
Re‑use:
Avatar
now works anywhere—profiles, comments, navbars. -
Isolation: Styling or testing
Avatar
won’t risk breakingTweet
. - Readability: Each file focuses on one concern; future teammates thank you.
3 Checklist: should I extract this?
- Does this UI fragment repeat?
- Would naming it make my parent component easier to scan?
- Could it be usefully mocked/stubbed in tests?
- Does it need its own state or side‑effects?
A “yes” to any question is a strong hint to spin it out.
4 Component extraction patterns worth exploring next
-
Compound Components – multiple pieces that share implicit state (think
Tabs
,FlyOut
). - Provider Pattern – avoid prop‑drilling by wrapping siblings in a context provider.
- Higher‑Order Components & Hooks – reuse logic without wrapper hell.
Conclusion
React rewards developers who think in components first. By mastering when and how to extract, you keep your codebase flexible, testable, and a joy to iterate on.
Content derived from “Learning Patterns” (Patterns.dev, CC BY‑NC 4.0).
Top comments (0)