React — Think in Components
What you'll learn
- The one idea behind React: components
- What props and state mean (with toys, not jargon)
- Rendering lists of components from an array — the pattern behind every feed, grid, and table
- Why real apps need useEffect to fetch data
- Write component-style code right here in the browser
- Know exactly what to install and study next
React itself needs a build setup, so our exercise uses plain JavaScript to practice the React way of thinking — the skill that actually matters.
LEGO blocks 🧱
Look at any app — Twitter/X for example. You'll see the same pieces repeated everywhere: a tweet card, a like button, an avatar.
React's whole idea: build each piece once as a component, then assemble your app from those pieces like LEGO.
A React component is literally just a function that returns what it looks like:
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
// use it like an HTML tag — as many times as you want:
<Welcome name="Sara" />
<Welcome name="Omar" />
Two words to own:
- Props = the knobs on the block.
<Welcome name="Sara" />passesnamein — same block, different output. Props go in, the component can't change them. - State = the block's memory. A like button remembers "am I liked? how many likes?" When state changes, React automatically redraws that component. You never manually do
element.textContent = ...again — that's the magic.
function LikeButton() {
const [likes, setLikes] = useState(0);
return <button onClick={() => setLikes(likes + 1)}>❤️ {likes}</button>;
}
useState(0) gives you the memory box and a setter. Call setLikes(...) and the button redraws itself. Compare that with the click counter you built in the JavaScript lesson — same result, but React does the DOM updating for you.
Practice component thinking (in plain JS — no build tools needed):
Write a function UserCard(name, role) that returns an HTML string for one card: a <div class="card"> containing an <h3> with the name and a <p> with the role.
Then render three different cards into #app by calling it three times (the starter shows how the first call is joined in).
Lists — the pattern behind every feed and grid 📃
In the exercise above you called UserCard three times, by hand. Real apps don't know how many items they'll have — a feed might have 3 posts or 3,000. React's answer is .map(): transform an array of data into an array of components, in one line:
const users = [
{ name: "Sara", role: "Designer" },
{ name: "Omar", role: "Developer" },
{ name: "Lina", role: "Manager" },
];
function App() {
return (
<div>
{users.map((u) => (
<UserCard key={u.name} name={u.name} role={u.role} />
))}
</div>
);
}
Add a 4th person to the users array and a 4th card appears automatically — no new <UserCard> line needed. That key={u.name} prop is required: it's a unique ID that helps React track which card is which when the list changes (adds, removes, reorders) — always give list items a stable, unique key.
This single pattern — data array → .map() → components — is how you'll build almost every list, grid, or feed you ever make in React.
Render from data, not by hand. Extend the card idea: instead of calling UserCard manually per person, build the HTML string by looping over the users array (plain JS for or .map() both work — this models what React's .map() does).
Requirements: render one .card per entry in users, each showing that person's name in an <h3>.
useEffect — fetching real data 🌐
Everything so far lives inside the browser. But real apps load data from a server — a list of products, a user's profile. React handles this with useEffect, which runs code after the component appears on screen:
function ProfilePage({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch("/api/users/" + userId)
.then((res) => res.json())
.then((data) => setUser(data));
}, [userId]); // re-run whenever userId changes
if (!user) return <p>Loading...</p>;
return <h1>{user.name}</h1>;
}
Read the [userId] at the end as "only re-run this fetch if userId changes" — without it, React would re-fetch on every single render, hammering your server. The pattern is always the same: start with null/loading state, fetch in useEffect, call setUser when data arrives, and React re-renders automatically with the real data. This exact pattern is how this platform's own Profile page loads your GitHub stats after you sign in.
Real-world case study: this site's own cards 🔍
Every roadmap card, certification card, and course card on this platform is one component, rendered exactly like the exercise above: a data array (data/roadmaps.ts, data/certifications.ts) is .map()-ed into a row of cards. Add a new roadmap to that one data file, and a new card appears on the site automatically — nobody hand-writes a new <RoadmapCard> line for it. That's the entire payoff of thinking in components: change the data, not the UI code.
Question 1 of 6
What is a React component?
Question 2 of 6
Props vs state — which is correct?
Question 3 of 6
What happens when you call setLikes(5)?
Question 4 of 6
Why did we return HTML from UserCard three times instead of copy-pasting the HTML three times?
Question 5 of 6
Why does React need a key prop when rendering a list with .map()?
Question 6 of 6
What does [userId] at the end of a useEffect call mean?
Your path into real React
You already think in components now. To write real React:
- Install Node.js (nodejs.org), then run:
npm create vite@latest my-app -- --template react - Follow the official tutorial at react.dev/learn — genuinely one of the best tutorials in software
- Rebuild the click counter and UserCard as real components with
useStateand props - Practice
.map()-ing a data array into a list of components, and fetching real data withuseEffect - The freeCodeCamp video in the Resources tab walks through everything on camera
Rule of thumb: if you catch yourself copy-pasting UI, that's a component waiting to be born. If you catch yourself writing the same component call for every item in a list, that's a .map() waiting to happen.
Practice
Reading is not learning until you run something. Pick one.