Components are the heart and soul of React. They let you split your UI into independent, reusable pieces that you can think about in isolation. In modern React, we use function components - simple JavaScript functions that return JSX. In this lesson, you'll learn everything about creating, organizing, and using function components to build amazing user interfaces.
What Are Components?
Think of components like LEGO blocks. Each block is a self-contained piece, and you combine them to build something bigger. In React:
- A component is a JavaScript function that returns JSX
- Each component represents a piece of your UI
- Components can be as small as a button or as large as an entire page
- You combine components to build complex interfaces
For example, a blog post page might have these components:
Component Hierarchy Example
Each box is a separate component. You can reuse them, test them independently, and maintain them easily.
Creating Your First Component
A function component is just a JavaScript function that returns JSX. Here's the simplest possible component:
function Welcome() {
return <h1>Hello, World!</h1>
}
// That's it! You've created a component.Using Your Component
Once you've created a component, you can use it like an HTML tag:
function Welcome() {
return <h1>Hello, World!</h1>
}
function App() {
return (
<div>
<Welcome />
<Welcome />
<Welcome />
</div>
)
}
// This renders "Hello, World!" three times!⚠️ Component Naming Rule
Component names must start with a capital letter!Welcome ✅ is a componentwelcome ❌ is treated as an HTML tag
This is how React distinguishes components from regular HTML elements.
Component Syntax Variations
There are several ways to write function components. They all work the same way - pick the style you prefer:
1. Function Declaration (Most Common)
function Greeting() {
return <h1>Hello!</h1>
}
// Clear, readable, easy to debug2. Arrow Function with Return
const Greeting = () => {
return <h1>Hello!</h1>
}
// Modern JavaScript style3. Arrow Function with Implicit Return
const Greeting = () => <h1>Hello!</h1>
// Very concise for simple components
// For multi-line JSX, use parentheses:
const Card = () => (
<div className="card">
<h2>Title</h2>
<p>Content</p>
</div>
)4. Function Expression
const Greeting = function() {
return <h1>Hello!</h1>
}
// Less common, but validWhich should you use?
Most React developers use function declarations because they're hoisted (can be used before they're defined) and show up nicely in debugging tools. But any syntax works fine - consistency matters more than the specific style you choose!
Adding Logic to Components
Components can contain any JavaScript logic before the return statement:
Variables and Calculations
function UserGreeting() {
// Variables
const userName = "Alice"
const currentHour = new Date().getHours()
// Calculations
const greeting = currentHour < 12 ? "Good morning" :
currentHour < 18 ? "Good afternoon" :
"Good evening"
// Computations
const displayName = userName.toUpperCase()
return (
<div>
<h1>{greeting}, {displayName}!</h1>
<p>It's currently {currentHour}:00</p>
</div>
)
}Functions Inside Components
function Calculator() {
const multiply = (a, b) => a * b
const add = (a, b) => a + b
const result1 = multiply(5, 3)
const result2 = add(10, 20)
return (
<div>
<p>5 × 3 = {result1}</p>
<p>10 + 20 = {result2}</p>
</div>
)
}Conditional Logic
function StatusMessage() {
const isOnline = true
const messageCount = 5
// Early return for one condition
if (!isOnline) {
return <p>You are offline</p>
}
// Variable for complex logic
let statusText
if (messageCount === 0) {
statusText = "No new messages"
} else if (messageCount === 1) {
statusText = "1 new message"
} else {
statusText = `${messageCount} new messages`
}
return (
<div>
<p>You are online</p>
<p>{statusText}</p>
</div>
)
}Multiple Components in One File
You can define multiple components in a single file. This is useful for small, related components:
// Helper components
function Avatar() {
return (
<img
src="/avatar.jpg"
alt="User avatar"
className="avatar"
/>
)
}
function UserInfo() {
return (
<div>
<h3>John Doe</h3>
<p>Software Developer</p>
</div>
)
}
function Status() {
return <span className="status-online">Online</span>
}
// Main component using the helpers
function UserCard() {
return (
<div className="user-card">
<Avatar />
<UserInfo />
<Status />
</div>
)
}
// Export only the main component
export default UserCard📁 File Organization Tip
It's fine to have multiple small components in one file if they're closely related. But if a component gets large or is used in multiple places, move it to its own file!
Organizing Component Files
As your app grows, you'll want to organize components into separate files. Here's the recommended structure:
Basic File Structure
src/
├── components/
│ ├── Button.jsx # Simple component
│ ├── Card.jsx
│ └── UserProfile.jsx
├── App.jsx
└── main.jsxFolder-Based Structure (For Complex Components)
src/
├── components/
│ ├── Button/
│ │ ├── Button.jsx
│ │ ├── Button.module.css
│ │ └── index.js # Re-export for cleaner imports
│ ├── UserProfile/
│ │ ├── UserProfile.jsx
│ │ ├── UserProfile.module.css
│ │ ├── Avatar.jsx # Sub-component
│ │ └── index.js
│ └── ...
├── App.jsx
└── main.jsxExporting Components
// Default export (most common)
function Button() {
return <button>Click me</button>
}
export default Button
// Or inline:
export default function Button() {
return <button>Click me</button>
}// Re-export for cleaner imports
export { default } from './Button'
// Or for named exports:
export { Button } from './Button'Importing Components
// Default import
import Button from './components/Button'
import UserProfile from './components/UserProfile'
// With index.js re-export
import Button from './components/Button' // Automatically uses index.js
// Named import (if using named export)
import { Button } from './components/Button'
function App() {
return (
<div>
<UserProfile />
<Button />
</div>
)
}Reusing Components
One of the biggest benefits of components is reusability. You can use the same component multiple times:
function ProductCard() {
return (
<div className="product-card">
<img src="/product.jpg" alt="Product" />
<h3>Product Name</h3>
<p>$99.99</p>
<button>Add to Cart</button>
</div>
)
}
function ProductGrid() {
return (
<div className="grid">
<ProductCard />
<ProductCard />
<ProductCard />
<ProductCard />
<ProductCard />
<ProductCard />
</div>
)
}
// All six cards are identical (for now - we'll learn about props next!)Nesting Components
Components can contain other components, creating a tree-like structure:
function Avatar() {
return <img src="/avatar.jpg" alt="User" className="avatar" />
}
function UserInfo() {
return (
<div className="user-info">
<h3>Jane Smith</h3>
<p>Product Designer</p>
</div>
)
}
function UserCard() {
return (
<div className="user-card">
<Avatar /> {/* Nested component */}
<UserInfo /> {/* Nested component */}
</div>
)
}
function Dashboard() {
return (
<div className="dashboard">
<h1>Team Members</h1>
<UserCard /> {/* Nested component */}
<UserCard />
<UserCard />
</div>
)
}This creates a component hierarchy:
Dashboard
└── UserCard (× 3)
├── Avatar
└── UserInfoComponent Rules and Best Practices
Rule 1: Component Names Must Be Capitalized
// ✅ Correct - Capitalized
function Button() {
return <button>Click me</button>
}
// ❌ Wrong - lowercase
function button() {
return <button>Click me</button>
}
// React treats lowercase as HTML tags
<button /> // Creates <button> HTML element
<Button /> // Renders your Button componentRule 2: Components Must Return JSX (or null)
// ✅ Correct - Returns JSX
function Welcome() {
return <h1>Hello!</h1>
}
// ✅ Also correct - Returns null
function ConditionalComponent({ show }) {
if (!show) return null
return <div>Content</div>
}
// ❌ Wrong - No return statement
function Broken() {
const content = <h1>Hello!</h1>
// Forgot to return!
}
// ❌ Wrong - Returns plain string
function AlsoBroken() {
return "Hello" // Must return JSX, not string
}Rule 3: One Component Per File (Usually)
// ✅ Good - One main component exported
function Card() {
return <div className="card">Content</div>
}
export default Card
// ✅ Also fine - Small helper components in same file
function CardHeader() {
return <div className="card-header">Header</div>
}
function CardBody() {
return <div className="card-body">Body</div>
}
function Card() {
return (
<div className="card">
<CardHeader />
<CardBody />
</div>
)
}
export default Card // Only export the main oneBest Practice: Keep Components Small and Focused
// ❌ Too large - does too many things
function UserDashboard() {
return (
<div>
<header>
<img src="/logo.png" alt="Logo" />
<nav>
<a href="/home">Home</a>
<a href="/profile">Profile</a>
</nav>
<button>Logout</button>
</header>
<main>
<aside>
<h2>Navigation</h2>
<ul>
<li>Dashboard</li>
<li>Settings</li>
</ul>
</aside>
<article>
{/* 100 more lines of JSX... */}
</article>
</main>
<footer>
{/* Footer content */}
</footer>
</div>
)
}
// ✅ Better - Split into smaller components
function Header() {
return (
<header>
<Logo />
<Navigation />
<LogoutButton />
</header>
)
}
function Sidebar() {
return (
<aside>
<h2>Navigation</h2>
<NavigationList />
</aside>
)
}
function MainContent() {
return (
<article>
{/* Content here */}
</article>
)
}
function UserDashboard() {
return (
<div>
<Header />
<main>
<Sidebar />
<MainContent />
</main>
<Footer />
</div>
)
}Best Practice: Use Descriptive Names
// ❌ Vague names
function Item() { }
function Box() { }
function Thing() { }
// ✅ Descriptive names
function ProductCard() { }
function UserProfile() { }
function ShoppingCart() { }
function NavigationMenu() { }
function CommentList() { }Best Practice: Extract Repeated JSX
// ❌ Repeated JSX
function ProductList() {
return (
<div>
<div className="product">
<img src="/product1.jpg" alt="Product" />
<h3>Product 1</h3>
<p>$29.99</p>
<button>Add to Cart</button>
</div>
<div className="product">
<img src="/product2.jpg" alt="Product" />
<h3>Product 2</h3>
<p>$39.99</p>
<button>Add to Cart</button>
</div>
{/* More repeated structure... */}
</div>
)
}
// ✅ Extracted to component
function ProductCard({ image, name, price }) {
return (
<div className="product">
<img src={image} alt={name} />
<h3>{name}</h3>
<p>${price}</p>
<button>Add to Cart</button>
</div>
)
}
function ProductList() {
return (
<div>
<ProductCard image="/product1.jpg" name="Product 1" price={29.99} />
<ProductCard image="/product2.jpg" name="Product 2" price={39.99} />
</div>
)
}Common Component Mistakes
1. Calling Component as Function
function Welcome() {
return <h1>Hello!</h1>
}
// ❌ Wrong - Calling as function
function App() {
return (
<div>
{Welcome()} {/* Don't do this! */}
</div>
)
}
// ✅ Correct - Using as JSX
function App() {
return (
<div>
<Welcome /> {/* This is the right way */}
</div>
)
}2. Lowercase Component Names
// ❌ Wrong - lowercase name
function welcome() {
return <h1>Hello!</h1>
}
function App() {
return <welcome /> // React thinks this is an HTML tag!
}
// ✅ Correct - Capitalized
function Welcome() {
return <h1>Hello!</h1>
}
function App() {
return <Welcome />
}3. Forgetting to Return
// ❌ Wrong - No return
function Greeting() {
const message = <h1>Hello!</h1>
// Forgot to return!
}
// ✅ Correct
function Greeting() {
const message = <h1>Hello!</h1>
return message
}
// ✅ Or directly
function Greeting() {
return <h1>Hello!</h1>
}4. Trying to Modify Props
// ❌ Wrong - Props are read-only!
function Counter(props) {
props.count = props.count + 1 // Error! Can't modify props
return <div>{props.count}</div>
}
// ✅ Correct - We'll learn about state in later lessons
function Counter(props) {
// Just read props, don't modify them
return <div>{props.count}</div>
}Key Takeaways
- Components are JavaScript functions that return JSX
- Component names must start with a capital letter
- Use components like HTML tags:
<MyComponent /> - Components can contain logic before the return statement
- You can nest components to build complex UIs
- Reuse components to avoid repeating code
- Keep components small and focused on one task
- Organize components into separate files as your app grows
- Extract repeated JSX into reusable components
- Components must return JSX or null
- Never call components as functions - use JSX syntax
- Props are read-only - never modify them directly
What's Next?
You now know how to create and use function components - the building blocks of React applications! But right now, all our components are static. They always render the same thing.
What if you want to make components dynamic and reusable with different data? That's where props come in! In the next lesson, you'll learn how to pass data between components, making them truly flexible and reusable. Get ready to supercharge your components! 🚀