What are Components?
Components are independent, reusable pieces of UI. Think of them like LEGO blocks - you build small pieces and combine them to create complex applications.
Component Benefits:
- Reusable: Write once, use everywhere
- Maintainable: Easy to update and debug
- Testable: Test each piece independently
- Composable: Combine to build complex UIs
🎯 Function Components (Modern React)
The standard way to create components in React 2025:
// Simple component
function Welcome() {
return <h1>Hello, World!</h1>;
}
// Export to use in other files
export default Welcome;
// Use the component
function App() {
return (
<div>
<Welcome />
<Welcome />
<Welcome />
</div>
);
}
Arrow Function Components:
// Also valid (same as above)
const Welcome = () => {
return <h1>Hello, World!</h1>;
};
// With implicit return (no curly braces)
const Welcome = () => <h1>Hello, World!</h1>;
export default Welcome;
📦 Props (Properties)
Pass data from parent to child components using props:
// Component with props
function Greeting(props) {
return <h1>Hello, {props.name}!</h1>;
}
// Using the component
function App() {
return (
<div>
<Greeting name="Alice" />
<Greeting name="Bob" />
<Greeting name="Charlie" />
</div>
);
}
// Output:
// Hello, Alice!
// Hello, Bob!
// Hello, Charlie!
Destructuring Props (Cleaner Syntax):
// Without destructuring
function UserCard(props) {
return (
<div>
<h2>{props.name}</h2>
<p>Age: {props.age}</p>
<p>Email: {props.email}</p>
</div>
);
}
// With destructuring (recommended)
function UserCard({ name, age, email }) {
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
<p>Email: {email}</p>
</div>
);
}
// Usage
<UserCard
name="Sarah"
age={25}
email="sarah@example.com"
/>
Different Types of Props:
function Product({ name, price, inStock, tags, onBuy }) {
return (
<div>
{/* String prop */}
<h3>{name}</h3>
{/* Number prop */}
<p>${price}</p>
{/* Boolean prop */}
<p>{inStock ? 'In Stock' : 'Out of Stock'}</p>
{/* Array prop */}
<p>Tags: {tags.join(', ')}</p>
{/* Function prop */}
<button onClick={onBuy}>Buy Now</button>
</div>
);
}
// Usage
<Product
name="Laptop"
price={999}
inStock={true}
tags={['electronics', 'computers']}
onBuy={() => alert('Added to cart!')}
/>
👶 Props.children
Special prop for nested content:
// Container component
function Card({ children }) {
return (
<div className="card">
{children}
</div>
);
}
// Usage - anything between tags becomes children
function App() {
return (
<Card>
<h2>Card Title</h2>
<p>Card content goes here</p>
<button>Click Me</button>
</Card>
);
}
⚙️ Default Props
// Method 1: Default parameters
function Button({ text = 'Click Me', color = 'blue' }) {
return (
<button style={{ backgroundColor: color }}>
{text}
</button>
);
}
// Method 2: Destructuring with fallback
function Button(props) {
const { text = 'Click Me', color = 'blue' } = props;
return (
<button style={{ backgroundColor: color }}>
{text}
</button>
);
}
// Usage
<Button /> {/* Uses defaults */}
<Button text="Submit" color="green" /> {/* Custom values */}
🔄 Component Composition
Build complex UIs by combining simple components:
// Small, focused components
function Avatar({ src, alt }) {
return <img src={src} alt={alt} className="avatar" />;
}
function UserName({ name }) {
return <h3>{name}</h3>;
}
function UserBio({ bio }) {
return <p>{bio}</p>;
}
// Compose them together
function UserProfile({ user }) {
return (
<div className="profile">
<Avatar src={user.avatar} alt={user.name} />
<UserName name={user.name} />
<UserBio bio={user.bio} />
</div>
);
}
// Use the composed component
function App() {
const user = {
name: "Alice Johnson",
avatar: "alice.jpg",
bio: "Software Developer"
};
return <UserProfile user={user} />;
}
📁 Component File Structure
src/
├── components/
│ ├── Button/
│ │ ├── Button.jsx
│ │ └── Button.css
│ ├── Card/
│ │ ├── Card.jsx
│ │ └── Card.css
│ └── Navbar/
│ ├── Navbar.jsx
│ └── Navbar.css
├── App.jsx
└── main.jsx
Button.jsx Example:
// Button.jsx
import './Button.css';
function Button({ text, onClick, variant = 'primary' }) {
return (
<button
className={`btn btn-${variant}`}
onClick={onClick}
>
{text}
</button>
);
}
export default Button;
Importing in App.jsx:
// App.jsx
import Button from './components/Button/Button';
import Card from './components/Card/Card';
import Navbar from './components/Navbar/Navbar';
function App() {
return (
<div>
<Navbar />
<Card>
<h2>Welcome</h2>
<Button text="Get Started" />
</Card>
</div>
);
}
🎨 Complete Example: Product Card
// ProductCard.jsx
import './ProductCard.css';
function ProductCard({ product }) {
const { name, price, image, rating, inStock } = product;
const handleAddToCart = () => {
alert(`Added ${name} to cart!`);
};
return (
<div className="product-card">
{/* Product Image */}
<img src={image} alt={name} className="product-image" />
{/* Stock Badge */}
{!inStock && (
<span className="out-of-stock-badge">Out of Stock</span>
)}
{/* Product Info */}
<div className="product-info">
<h3>{name}</h3>
{/* Rating */}
<div className="rating">
{'⭐'.repeat(rating)} ({rating}/5)
</div>
{/* Price */}
<p className="price">${price.toFixed(2)}</p>
{/* Add to Cart Button */}
<button
onClick={handleAddToCart}
disabled={!inStock}
className={inStock ? 'btn-primary' : 'btn-disabled'}
>
{inStock ? 'Add to Cart' : 'Unavailable'}
</button>
</div>
</div>
);
}
export default ProductCard;
// Usage in App
function App() {
const products = [
{
name: "Wireless Headphones",
price: 79.99,
image: "headphones.jpg",
rating: 4,
inStock: true
},
{
name: "Smart Watch",
price: 199.99,
image: "watch.jpg",
rating: 5,
inStock: false
}
];
return (
<div className="product-grid">
{products.map((product, index) => (
<ProductCard key={index} product={product} />
))}
</div>
);
}
⚠️ Component Rules
- Names start with capital letter:
MyComponentnotmyComponent - Must return JSX: Or null, but must return something
- Props are read-only: Never modify props directly
- One component per file: Better organization (usually)
- Pure functions: Same props = same output
🎯 Key Takeaways
- Components: Reusable UI building blocks
- Function components: Modern React standard
- Props: Pass data from parent to child
- Destructuring: Clean way to access props
- props.children: For nested content
- Composition: Combine small components
- Capital letters: Component names must start with uppercase
- Pure functions: Same input = same output