Chapter 3: Components
What is a Component?
A component is a JavaScript function that returns JSX:
function Welcome() {
return <h1>Hello!</h1>;
}
That's it. A function that returns UI.
Naming Conventions
- PascalCase for component names:
UserCard,LoginForm,NavigationMenu - Components starting with lowercase are treated as HTML tags
// CORRECT
function UserCard() { ... }
<UserCard />
// INCORRECT - treated as HTML tag <usercard>
function userCard() { ... }
<userCard /> // Doesn't work!
Props: Passing Data
Props (properties) allow you to pass data to a component:
// Component definition with props
function Welcome({ name }) {
return <h1>Hello, {name}!</h1>;
}
// Usage
<Welcome name="Jean" />
<Welcome name="Marie" />
Multiple Props
function UserCard({ name, email, role }) {
return (
<div className="card">
<h2>{name}</h2>
<p>{email}</p>
<span>{role}</span>
</div>
);
}
<UserCard name="Jean" email="jean@example.com" role="Admin" />
Props with Default Values
function Button({ label, type = "button", disabled = false }) {
return (
<button type={type} disabled={disabled}>
{label}
</button>
);
}
<Button label="Submit" />
<Button label="Submit" type="submit" />
<Button label="Disabled" disabled={true} />
Different Prop Types
function Product({ name, price, inStock, tags, onClick }) {
return (
<div onClick={onClick}>
<h3>{name}</h3>
<p>{price} €</p>
{inStock && <span>In Stock</span>}
<ul>
{tags.map(tag => <li key={tag}>{tag}</li>)}
</ul>
</div>
);
}
<Product
name="Laptop"
price={999}
inStock={true}
tags={['tech', 'sale']}
onClick={() => console.log('Clicked')}
/>
| Type | Example |
|---|---|
| String | name="Jean" |
| Number | age={30} |
| Boolean | active={true} or just active |
| Array | items={[1, 2, 3]} |
| Object | user={{ name: 'Jean' }} |
| Function | onClick={() => {}} |
Children Prop
The special children prop contains the content between the opening and closing tags:
function Card({ title, children }) {
return (
<div className="card">
<h2>{title}</h2>
<div className="card-body">
{children}
</div>
</div>
);
}
// Usage
<Card title="My Title">
<p>This is the card content.</p>
<button>Action</button>
</Card>
This is very useful for creating "wrapper" or "layout" components.
Component Composition
Components can use other components:
function Avatar({ src, alt }) {
return <img className="avatar" src={src} alt={alt} />;
}
function UserInfo({ name, email }) {
return (
<div className="user-info">
<span className="name">{name}</span>
<span className="email">{email}</span>
</div>
);
}
function UserCard({ user }) {
return (
<div className="user-card">
<Avatar src={user.avatar} alt={user.name} />
<UserInfo name={user.name} email={user.email} />
</div>
);
}
function UserList({ users }) {
return (
<div className="user-list">
{users.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
);
}
Hierarchy: UserList -> UserCard -> Avatar + UserInfo
Props are Read-Only
Fundamental rule: a component should never modify its props.
// INCORRECT - never do this!
function BadComponent({ user }) {
user.name = "Modified"; // FORBIDDEN!
return <div>{user.name}</div>;
}
// CORRECT - props are immutable
function GoodComponent({ user }) {
return <div>{user.name}</div>;
}
If you need to modify data, use state (useState - next module).
Prop Destructuring
Several ways to extract props:
// 1. Destructuring in parameters (recommended)
function UserCard({ name, email }) {
return <div>{name} - {email}</div>;
}
// 2. Destructuring in body
function UserCard(props) {
const { name, email } = props;
return <div>{name} - {email}</div>;
}
// 3. Without destructuring
function UserCard(props) {
return <div>{props.name} - {props.email}</div>;
}
Prop Spread
To forward all props to a child element:
function Button({ children, ...rest }) {
return (
<button className="btn" {...rest}>
{children}
</button>
);
}
// Usage - onClick and disabled are passed to button
<Button onClick={handleClick} disabled={isLoading}>
Submit
</Button>
File Organization
SmartMaker convention: one component per folder with index.jsx:
src/components/
├── UserCard/
│ └── index.jsx
├── UserList/
│ └── index.jsx
└── common/
├── Button/
│ └── index.jsx
└── Card/
└── index.jsx
// src/components/UserCard/index.jsx
export default function UserCard({ user }) {
return (
<div className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
);
}
// Import
import UserCard from 'src/components/UserCard';
Exercises
Exercise 1: Create a Button Component
Create a Button component that accepts:
label: button textvariant: "primary" or "secondary" (default: "primary")onClick: function to call on click
Solution:
function Button({ label, variant = "primary", onClick }) {
return (
<button
className={`btn btn-${variant}`}
onClick={onClick}
>
{label}
</button>
);
}
// Usage
<Button label="Submit" onClick={() => console.log('Submitted')} />
<Button label="Cancel" variant="secondary" onClick={handleCancel} />
Exercise 2: Composition
Create a component structure to display a list of products:
ProductList: receives an array of productsProductCard: displays a product (name, price)Price: displays a formatted price with € symbol
Solution:
function Price({ value }) {
return <span className="price">{value.toFixed(2)} €</span>;
}
function ProductCard({ product }) {
return (
<div className="product-card">
<h3>{product.name}</h3>
<Price value={product.price} />
</div>
);
}
function ProductList({ products }) {
return (
<div className="product-list">
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
// Usage
const products = [
{ id: 1, name: 'Laptop', price: 999.99 },
{ id: 2, name: 'Phone', price: 699.50 }
];
<ProductList products={products} />
Key Points to Remember
- Component = function that returns JSX
- PascalCase for component names
- Props: data passed to the component (read-only)
- children: content between the tags
- Composition: components that use other components
- Destructuring:
function Component({ prop1, prop2 })
Module 2 Summary
You now know the basics of React:
| Concept | Description |
|---|---|
| JSX | Syntax for writing UI in JavaScript |
| Component | Function that returns JSX |
| Props | Data passed to a component |
| children | Content between tags |
| key | Unique identifier for lists |
| Fragment | <></> to return multiple elements |
<- Previous Chapter | Back to Module | Next Module: Fundamentals Hooks ->