⚛️ React Basics: Components, Props, and JSX
Modern web applications are incredibly complex. If you try to build Facebook using pure HTML and document.createElement, your codebase will collapse into an unmaintainable nightmare within weeks.
React.js, developed by Facebook, revolutionized the industry by introducing two core concepts: Components (breaking the UI into reusable Lego blocks) and a Declarative Paradigm (telling React what you want the UI to look like, rather than how to build it step-by-step).
1️⃣ Component-Based Architecture
Before React, developers built web pages as single, massive files (index.html).
React forces you to think of your user interface as a collection of independent, isolated Components.
What is a Component?
A React Component is mathematically just a regular JavaScript function that returns HTML.
// A valid React Component
function WelcomeMessage() {
return <h1>Hello, Mwero!</h1>;
}
// Rendering it somewhere else
function App() {
return (
<div>
<WelcomeMessage />
<WelcomeMessage />
</div>
);
}
Notice that by creating <WelcomeMessage />, you essentially invented a brand new custom HTML tag that you can reuse infinitely.
2️⃣ JSX: JavaScript XML
In the code above, we returned <h1> tags directly inside a JavaScript function. Historically, this was illegal. JavaScript cannot understand HTML tags.
JSX (JavaScript XML) is a syntactic extension. It allows us to write HTML-like code inside JS files. Under the hood, a compiler (like Babel) intercepts the JSX and translates it into massive React.createElement() function calls before it reaches the browser.
The 3 Rules of JSX
1. You must return a single root element.
// ❌ INVALID: Returning two sibling elements
return (
<h1>Title</h1>
<p>Subtitle</p>
);
// ✅ VALID: Wrapping them in a Fragment (which renders no HTML node)
return (
<>
<h1>Title</h1>
<p>Subtitle</p>
</>
);
2. You MUST close all tags.
In HTML, <img src="a.jpg"> and <input> are fine. In JSX, they will crash your app. They must be self-closing: <img /> and <input />.
3. CamelCase for Attributes.
HTML attributes like class and onclick become className and onClick.
// ❌ HTML
<button class="btn" onclick="sayHi()">Click</button>
// ✅ JSX
<button className="btn" onClick={sayHi}>Click</button>
3️⃣ Interpolation: Injecting JavaScript into JSX
JSX allows you to escape out of HTML mode and back into JavaScript mode by dropping curly braces {} anywhere.
function UserProfile() {
const username = "Admin";
const age = 30;
const isVerified = true;
return (
<div className="card">
{/* Injecting raw variables */}
<h1>{username}</h1>
<p>Age in 5 years: {age + 5}</p>
{/* Conditional Rendering (The Ternary Operator) */}
{isVerified ? <span className="badge">Verified</span> : null}
{/* Conditional Rendering (The && Operator) */}
{isVerified && <p>Thank you for verifying!</p>}
</div>
);
}
4️⃣ Props: Passing Data Downward
Components are isolated. The <Post /> component knows nothing about the <App /> component. How do we pass the username from the App down into the Post?
We use Props (Properties). Props are how data flows downwards in React.
// 1. Passing the props
function App() {
return (
<div className="dashboard">
<UserBadge name="Alice" role="Admin" />
<UserBadge name="Bob" role="User" />
</div>
);
}
// 2. Receiving the props (Props is just a massive Object)
function UserBadge(props) {
return (
<div className="badge">
<h2>{props.name}</h2>
<p>Role: {props.role}</p>
</div>
);
}
The Professional Way: Destructuring Props
Typing props. 100 times per file is exhausting. Professionals immediately destructure the object in the function parameters.
/* ✅ Destructured Props */
function UserBadge({ name, role }) {
return (
<div className="badge">
<h2>{name}</h2>
<p>Role: {role}</p>
</div>
);
}
5️⃣ Rendering Lists (.map)
When fetching 100 products from a database, you cannot manually write 100 <ProductCard /> tags. You must loop over the data array.
In React, we use the Array.map() method to transform an array of data into an array of JSX elements.
function ShoppingCart() {
const items = ["Apples", "Bananas", "Milk"];
return (
<ul>
{items.map((item, index) => {
// Warning: Every item in a mapped list MUST have a unique 'key' prop!
return <li key={index}>{item}</li>
})}
</ul>
);
}
Note: Using the array index as a key is frowned upon in dynamic lists that delete items. Always try to use a unique database ID like key={item.id}.
💡 Summary Checklist
- I understand that a Component is just a JavaScript function returning JSX.
- I always wrap multiple sibling elements in a
<> Fragment </>. - I use
classNameinstead ofclassin React. - I use
{}curlies to inject JS variables and logic into JSX. - I know that Props flow one direction: Downward from Parent to Child.
- I destructure my
{ props }for cleaner code. - I always provide a unique
keyprop when rendering lists with.map().