🧩 Components

Building Blocks of React Applications

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

🎯 Key Takeaways