Thinking in components
Break a screen into small pieces, each responsible for one part of the UI.
- Read a mockup and sketch the components before writing code.
- Pass data down with props and report changes up with callbacks.
- Lift shared state to the nearest common parent.
- Split a component when it starts doing more than one job.
In plain English
A component is a function that returns part of the screen. Props are the read-only inputs a parent passes down, while state is data the component owns and can change. When two siblings need the same value, you lift the state to their nearest common parent and pass it down as props. Good component boundaries keep each piece small enough to understand at a glance.
Step by step
- 1Draw boxes around each visible piece of the screen.
- 2Name each box and note what data it needs and what it changes.
- 3Decide which pieces own state and which only receive props.
- 4Write the leaf components first, then compose them into parents.
type StudyItem = {
id: string
title: string
minutes: number
}
function StudyItemRow({ item, onSelect }: { item: StudyItem; onSelect: (id: string) => void }) {
return (
<li>
<button onClick={() => onSelect(item.id)}>
{item.title} ({item.minutes} min)
</button>
</li>
)
}
function StudyList({ items, onSelect }: { items: StudyItem[]; onSelect: (id: string) => void }) {
return (
<ul>
{items.map((item) => (
<StudyItemRow key={item.id} item={item} onSelect={onSelect} />
))}
</ul>
)
}Common mistakes
- Putting every piece of state in the top component makes props travel through too many layers for no reason.
- Copying the same value into two siblings instead of lifting it means the two copies drift apart over time.
- Splitting components too aggressively scatters related logic, so wait until a component is genuinely hard to read.
- Mutating a prop to report a change breaks the one-way data flow and hides bugs.
Split a card into components
Split a LessonCard into a LessonTitle and a LessonFooter component, passing the title down as a prop and the onOpen callback through.
function LessonCard({ title, minutes, onOpen }: { title: string; minutes: number; onOpen: () => void }) {
return (
<article>
<h3>{title}</h3>
<p>{minutes} min</p>
<button onClick={onOpen}>Open</button>
</article>
)
}When two sibling components need to share the same value, where should the state live?
Make it yours.
Keep a private note for this lesson, then turn the key ideas into flashcards you can revisit.
Lock in what you just learned.
Mark this lesson complete to save your place and move one step closer to the certificate.