What are Components?

Components are the heart of React. Think of them as custom HTML elements that you can create, customize, and reuse throughout your application. Just like you use <div>, <button>, or <input> elements, you can create your own components like <Header>, <UserProfile>, or <ProductCard>.

Vanilla JavaScript Approach
HTML + JavaScript
// HTML
<div id="user-cards"></div>

// JavaScript
function createUserCard(user) {
  return `
    <div class="user-card">
      <img src="${user.avatar}" alt="${user.name}">
      <h3>${user.name}</h3>
      <p>${user.email}</p>
      <button onclick="followUser(${user.id})">
        Follow
      </button>
    </div>
  `;
}

// Usage
document.getElementById('user-cards').innerHTML = 
  users.map(createUserCard).join('');
React Component Approach
React JSX
// UserCard Component
function UserCard({ user, onFollow }) {
  return (
    <div className="user-card">
      <img src={user.avatar} alt={user.name} />
      <h3>{user.name}</h3>
      <p>{user.email}</p>
      <button onClick={() => onFollow(user.id)}>
        Follow
      </button>
    </div>
  );
}

// Usage
<div>
  {users.map(user => 
    <UserCard 
      key={user.id} 
      user={user} 
      onFollow={followUser} 
    />
  )}
</div>

Understanding JSX

JSX (JavaScript XML) is React's syntax extension that lets you write HTML-like code in JavaScript. It might look strange at first, but it's just a more intuitive way to describe what your UI should look like.

๐ŸŽฏ JSX is NOT HTML

While JSX looks like HTML, it's actually JavaScript. Here are the key differences:

JSX vs HTML
// JSX uses className instead of class
<div className="container">Content</div>

// JSX uses camelCase for attributes
<input onClick={handleClick} onChange={handleChange} />

// JSX requires self-closing tags
<img src="image.jpg" alt="Description" />
<br />
<input type="text" />

// JSX can embed JavaScript expressions
<h1>Hello, {user.name}!</h1>
<div style={{color: 'red', fontSize: '16px'}}>
  Dynamic content
</div>

๐Ÿ”„ How JSX Works

JSX gets compiled to regular JavaScript function calls. Here's what happens under the hood:

What You Write (JSX)
JSX
<div className="greeting">
  <h1>Hello, {name}!</h1>
  <p>Welcome to React</p>
</div>
What React Sees (JavaScript)
JavaScript
React.createElement(
  'div',
  { className: 'greeting' },
  React.createElement('h1', null, 'Hello, ', name, '!'),
  React.createElement('p', null, 'Welcome to React')
);

Functional Components

Modern React uses functional components - JavaScript functions that return JSX. They're simple, easy to understand, and work great with React Hooks.

Basic Functional Component
// Simple component with no props
function Welcome() {
  return <h1>Welcome to our website!</h1>;
}

// Component with props
function Greeting({ name, age }) {
  return (
    <div>
      <h2>Hello, {name}!</h2>
      <p>You are {age} years old.</p>
    </div>
  );
}

// Component with conditional rendering
function UserStatus({ isLoggedIn, username }) {
  return (
    <div>
      {isLoggedIn ? (
        <p>Welcome back, {username}!</p>
      ) : (
        <p>Please log in to continue.</p>
      )}
    </div>
  );
}

๐Ÿ’ก Component Rules

  • Component names must start with a capital letter (e.g., UserCard, not userCard)
  • Components must return JSX (or null, string, number, or array)
  • Components can only return one root element (use fragments <></> or <div> wrapper)
  • Props are read-only - never modify them directly

Class Components (Legacy)

Before functional components and hooks, React used class components. You'll still see them in older codebases, so it's good to understand them.

Class Component
Class Component
import React, { Component } from 'react';

class Greeting extends Component {
  constructor(props) {
    super(props);
    this.state = {
      message: 'Hello!'
    };
  }

  render() {
    return (
      <div>
        <h1>{this.state.message}</h1>
        <p>Welcome, {this.props.name}!</p>
      </div>
    );
  }
}
Functional Component (Modern)
Functional Component
import React, { useState } from 'react';

function Greeting({ name }) {
  const [message, setMessage] = useState('Hello!');

  return (
    <div>
      <h1>{message}</h1>
      <p>Welcome, {name}!</p>
    </div>
  );
}

๐Ÿ“ Why Functional Components?

  • Simpler syntax - Less boilerplate code
  • Better performance - Easier to optimize
  • Hooks compatibility - Access to modern React features
  • Easier testing - Pure functions are easier to test

Component Composition

One of React's superpowers is component composition - building complex UIs by combining simple components.

Component Composition Example
// Small, focused components
function Avatar({ src, alt }) {
  return <img src={src} alt={alt} className="avatar" />;
}

function UserInfo({ name, email }) {
  return (
    <div className="user-info">
      <h3>{name}</h3>
      <p>{email}</p>
    </div>
  );
}

function ActionButton({ onClick, children }) {
  return (
    <button className="action-btn" onClick={onClick}>
      {children}
    </button>
  );
}

// Composed component using smaller components
function UserCard({ user, onFollow, onMessage }) {
  return (
    <div className="user-card">
      <Avatar src={user.avatar} alt={user.name} />
      <UserInfo name={user.name} email={user.email} />
      <div className="actions">
        <ActionButton onClick={() => onFollow(user.id)}>
          Follow
        </ActionButton>
        <ActionButton onClick={() => onMessage(user.id)}>
          Message
        </ActionButton>
      </div>
    </div>
  );
}

๐Ÿ”ง Reusability

Small components can be reused across different parts of your application.

๐Ÿงช Testability

Small components are easier to test in isolation.

๐Ÿ” Maintainability

When each component has a single responsibility, bugs are easier to find and fix.

๐Ÿ‘ฅ Team Collaboration

Different team members can work on different components simultaneously.

JSX Best Practices

โœ… Do's and Don'ts

โœ… Good Practices:

Good JSX
// Use descriptive component names
function UserProfileCard({ user }) { /* ... */ }

// Use fragments to avoid unnecessary divs
function App() {
  return (
    <>
      <Header />
      <MainContent />
      <Footer />
    </>
  );
}

// Use meaningful prop names
<Button 
  isLoading={isSubmitting} 
  disabled={!isFormValid}
  onClick={handleSubmit}
>
  Submit
</Button>

// Extract complex expressions
function TodoItem({ todo }) {
  const isOverdue = new Date(todo.dueDate) < new Date();
  
  return (
    <div className={isOverdue ? 'overdue' : 'normal'}>
      {todo.title}
    </div>
  );
}

โŒ Avoid:

Avoid These
// Don't modify props
function BadComponent({ user }) {
  user.name = user.name.toUpperCase(); // โŒ Never do this
  return <div>{user.name}</div>;
}

// Don't use array indices as keys (unless list never changes)
{items.map((item, index) => 
  <Item key={index} data={item} /> // โŒ Avoid
)}

// Don't put complex logic in JSX
<div>
  {/* โŒ Too complex */}
  {user.posts.filter(post => post.published)
              .sort((a, b) => new Date(b.date) - new Date(a.date))
              .slice(0, 5)
              .map(post => <Post key={post.id} post={post} />)}
</div>

What's Next?

Now that you understand components and JSX, you're ready to learn how components communicate with each other and manage their internal state.

๐Ÿš€ Continue Learning

  1. Props & State - Learn how data flows in React
  2. Event Handling - Make your components interactive
  3. Conditional Rendering - Show different content based on conditions
  4. React Hooks - Modern state management and side effects