Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
LoginSign Up
menu
  1. Home
  2. /Web Development
  3. /React
  4. /Component Composition
Your Progress0%
0 of 42 completed

React Topics

Getting Started

  • What is React?
  • React vs Vanilla JavaScript
  • Setting Up Your Environment
  • Your First React App

JSX Fundamentals

  • Introduction to JSX
  • JSX Expressions and Variables
  • Conditional Rendering
  • Lists and Keys
  • Styling in JSX

Components Basics

  • Function Components
  • Props
  • Children Prop
  • Props Destructuring
  • Component Composition

State Management

  • Introduction to State
  • useState Hook
  • State Updates and Re-renders
  • Multiple State Variables
  • State Best Practices

Events and Interactivity

  • Handling Events
  • Event Objects
  • Forms in React
  • Form Validation

Side Effects and Data

  • Introduction to useEffect
  • Data Fetching
  • Cleanup Functions
  • Dependency Arrays

Advanced Hooks

  • useRef Hook
  • useContext Hook
  • useMemo Hook
  • useCallback Hook

React Patterns

  • Custom Hooks
  • Higher-Order Components
  • Render Props Pattern

React Router

  • Introduction to React Router
  • Routes and Navigation
  • Dynamic Routes and Parameters

Best Practices

  • Component Organization
  • Performance Optimization
  • Error Handling
  • Testing React Components

Real World Project

  • Building a Complete App

Component Composition

Building complex UIs from simple building blocks

The true power of React isn't in individual components - it's in how you compose them together. Just like building with LEGO blocks, you create complex UIs by combining simple, focused components. This is called component composition, and it's the key to building maintainable, scalable React applications. In this lesson, you'll learn composition patterns, best practices, and how to architect your components for maximum reusability.

What is Component Composition?

Component composition means building complex components by combining simpler ones, rather than building one massive component that does everything.

The Problem: Monolithic Components

monolithic.jsx
// ❌ Bad - One giant component doing everything
function UserDashboard() {
  return (
    <div className="dashboard">
      {/* Header */}
      <header>
        <img src="/logo.png" alt="Logo" />
        <nav>
          <a href="/home">Home</a>
          <a href="/profile">Profile</a>
          <a href="/settings">Settings</a>
        </nav>
        <button>Logout</button>
      </header>
      
      {/* Sidebar */}
      <aside>
        <h2>Filters</h2>
        <label>
          <input type="checkbox" /> Active
        </label>
        <label>
          <input type="checkbox" /> Completed
        </label>
      </aside>
      
      {/* Main content */}
      <main>
        <h1>Tasks</h1>
        <div className="task-list">
          {/* 50+ lines of task rendering... */}
        </div>
      </main>
      
      {/* Footer */}
      <footer>
        <p>&copy; 2024 My App</p>
      </footer>
    </div>
  )
}

// This component:
// - Is hard to read (hundreds of lines)
// - Is hard to test
// - Can't reuse parts
// - Is hard to maintain

The Solution: Composition

composed.jsx
// ✅ Good - Small, focused components
function Logo() {
  return <img src="/logo.png" alt="Logo" />
}

function Navigation() {
  return (
    <nav>
      <a href="/home">Home</a>
      <a href="/profile">Profile</a>
      <a href="/settings">Settings</a>
    </nav>
  )
}

function Header() {
  return (
    <header>
      <Logo />
      <Navigation />
      <button>Logout</button>
    </header>
  )
}

function Sidebar() {
  return (
    <aside>
      <h2>Filters</h2>
      <FilterCheckbox label="Active" />
      <FilterCheckbox label="Completed" />
    </aside>
  )
}

function TaskList() {
  return (
    <div className="task-list">
      {/* Task rendering */}
    </div>
  )
}

function Footer() {
  return (
    <footer>
      <p>&copy; 2024 My App</p>
    </footer>
  )
}

// Main component - clean and readable!
function UserDashboard() {
  return (
    <div className="dashboard">
      <Header />
      <Sidebar />
      <main>
        <h1>Tasks</h1>
        <TaskList />
      </main>
      <Footer />
    </div>
  )
}

// Each component:
// - Has a single responsibility
// - Is easy to read and understand
// - Can be reused elsewhere
// - Is easy to test and maintain

Component Composition Hierarchy

App
Header
Logo
Navigation
UserMenu
Main
Sidebar
Content
Footer
Props
State
Click to expand/collapse

Composition Principles

1. Single Responsibility

Each component should do one thing well:

single-responsibility.jsx
// ❌ Component doing too much
function UserProfile() {
  return (
    <div>
      {/* Profile info */}
      <div className="profile">...</div>
      {/* Posts */}
      <div className="posts">...</div>
      {/* Friends list */}
      <div className="friends">...</div>
      {/* Settings */}
      <div className="settings">...</div>
    </div>
  )
}

// ✅ Each component has one job
function ProfileInfo() {
  return <div className="profile">...</div>
}

function PostsList() {
  return <div className="posts">...</div>
}

function FriendsList() {
  return <div className="friends">...</div>
}

function Settings() {
  return <div className="settings">...</div>
}

function UserProfile() {
  return (
    <div>
      <ProfileInfo />
      <PostsList />
      <FriendsList />
      <Settings />
    </div>
  )
}

2. Compose from the Bottom Up

Build small components first, then combine them into larger ones:

bottom-up.jsx
// Step 1: Smallest components (atoms)
function Button({ children, onClick }) {
  return (
    <button className="btn" onClick={onClick}>
      {children}
    </button>
  )
}

function Input({ label, value, onChange }) {
  return (
    <div>
      <label>{label}</label>
      <input value={value} onChange={onChange} />
    </div>
  )
}

// Step 2: Combine into medium components (molecules)
function SearchBox({ value, onChange, onSearch }) {
  return (
    <div className="search-box">
      <Input 
        label="Search" 
        value={value} 
        onChange={onChange} 
      />
      <Button onClick={onSearch}>Search</Button>
    </div>
  )
}

// Step 3: Combine into larger components (organisms)
function Header({ searchValue, onSearch, onSearchChange }) {
  return (
    <header>
      <Logo />
      <SearchBox 
        value={searchValue}
        onChange={onSearchChange}
        onSearch={onSearch}
      />
      <UserMenu />
    </header>
  )
}

// Step 4: Compose into pages (templates)
function HomePage() {
  return (
    <div>
      <Header />
      <MainContent />
      <Footer />
    </div>
  )
}

3. Use Props for Customization

props-customization.jsx
// ✅ Reusable through props
function Card({ title, image, description, action }) {
  return (
    <div className="card">
      {image && <img src={image} alt={title} />}
      <h3>{title}</h3>
      <p>{description}</p>
      {action && <div className="actions">{action}</div>}
    </div>
  )
}

// Same component, different uses
<Card 
  title="Product 1"
  image="/product1.jpg"
  description="Great product"
  action={<Button>Buy Now</Button>}
/>

<Card 
  title="Article"
  description="Interesting article"
  action={<Button>Read More</Button>}
/>

<Card 
  title="Simple Card"
  description="No image, no action"
/>

4. Use Children for Flexibility

children-flexibility.jsx
// ✅ Maximum flexibility with children
function Panel({ title, children }) {
  return (
    <div className="panel">
      <div className="panel-header">{title}</div>
      <div className="panel-body">{children}</div>
    </div>
  )
}

// Flexible usage
<Panel title="User Settings">
  <SettingsForm />
</Panel>

<Panel title="Statistics">
  <Chart data={chartData} />
  <Legend />
</Panel>

<Panel title="Notifications">
  <p>You have 5 new notifications</p>
  <NotificationList />
  <Button>Mark All Read</Button>
</Panel>

Common Composition Patterns

1. Container and Presentational Components

Separate logic (containers) from presentation (components):

container-presentational.jsx
// Presentational - just displays data
function UserList({ users, onUserClick }) {
  return (
    <ul>
      {users.map(user => (
        <li key={user.id} onClick={() => onUserClick(user)}>
          {user.name}
        </li>
      ))}
    </ul>
  )
}

// Container - handles logic and state
function UserListContainer() {
  const [users, setUsers] = React.useState([])
  const [loading, setLoading] = React.useState(true)
  
  React.useEffect(() => {
    fetch('/api/users')
      .then(res => res.json())
      .then(data => {
        setUsers(data)
        setLoading(false)
      })
  }, [])
  
  const handleUserClick = (user) => {
    console.log('Clicked:', user)
  }
  
  if (loading) return <div>Loading...</div>
  
  return <UserList users={users} onUserClick={handleUserClick} />
}

2. Layout Components

layout-pattern.jsx
// Reusable layout components
function TwoColumnLayout({ left, right }) {
  return (
    <div className="two-column">
      <div className="left-column">{left}</div>
      <div className="right-column">{right}</div>
    </div>
  )
}

function PageLayout({ header, sidebar, content, footer }) {
  return (
    <div className="page">
      <header>{header}</header>
      <div className="page-body">
        <aside>{sidebar}</aside>
        <main>{content}</main>
      </div>
      <footer>{footer}</footer>
    </div>
  )
}

// Usage
<PageLayout
  header={<Header />}
  sidebar={<Sidebar />}
  content={<MainContent />}
  footer={<Footer />}
/>

3. Specialized Components

specialized.jsx
// Generic button
function Button({ variant = 'primary', children, ...props }) {
  return (
    <button className={`btn btn-${variant}`} {...props}>
      {children}
    </button>
  )
}

// Specialized buttons built from generic Button
function PrimaryButton({ children, ...props }) {
  return <Button variant="primary" {...props}>{children}</Button>
}

function DangerButton({ children, ...props }) {
  return <Button variant="danger" {...props}>{children}</Button>
}

function SubmitButton({ children, ...props }) {
  return (
    <PrimaryButton type="submit" {...props}>
      {children || 'Submit'}
    </PrimaryButton>
  )
}

// Usage
<PrimaryButton onClick={handleSave}>Save</PrimaryButton>
<DangerButton onClick={handleDelete}>Delete</DangerButton>
<SubmitButton />  {/* Uses default "Submit" text */}

4. Higher-Order Composition

higher-order.jsx
// Wrapper component that adds functionality
function withLoading(Component) {
  return function LoadingWrapper({ isLoading, ...props }) {
    if (isLoading) {
      return <div>Loading...</div>
    }
    return <Component {...props} />
  }
}

// Original component
function UserProfile({ user }) {
  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  )
}

// Enhanced component with loading
const UserProfileWithLoading = withLoading(UserProfile)

// Usage
<UserProfileWithLoading 
  isLoading={loading} 
  user={userData} 
/>

Practical Example: Building a Card System

ReactPlayground.jsx
Code Editor
Preview

💡 Tip: Edit the code above and click "Run" to see your changes

Composition vs Inheritance

In traditional object-oriented programming, you use inheritance to reuse code. In React, we prefer composition:

❌ Inheritance (Not Recommended in React)

inheritance.jsx
// ❌ Don't do this in React
class BaseButton extends React.Component {
  render() {
    return <button className="btn">{this.props.children}</button>
  }
}

class PrimaryButton extends BaseButton {
  render() {
    return <button className="btn btn-primary">{this.props.children}</button>
  }
}

// Problems:
// - Tight coupling
// - Hard to modify base class
// - Can't easily combine multiple behaviors

✅ Composition (Recommended)

composition-recommended.jsx
// ✅ Do this instead
function Button({ variant = 'default', children, ...props }) {
  return (
    <button 
      className={`btn btn-${variant}`} 
      {...props}
    >
      {children}
    </button>
  )
}

// Just use props for variations
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>

// Easy to combine behaviors
<Button variant="primary" disabled>Disabled Primary</Button>
<Button variant="danger" onClick={handleDelete}>Delete</Button>

React Philosophy:

"Prefer composition over inheritance." React makes composition so easy and powerful that you rarely (if ever) need inheritance. Props and children give you all the flexibility you need!

Designing Component Hierarchies

Think in Components

When designing a UI, break it down into a component hierarchy:

  1. Draw boxes around every component and sub-component
  2. Name each component based on what it does
  3. Arrange them in a hierarchy - which components contain others?
  4. Identify what data each component needs
  5. Build from the bottom up - small to large

Example: Product Page Breakdown

component-hierarchy.txt
ProductPage
├── Header
│   ├── Logo
│   ├── SearchBar
│   │   ├── Input
│   │   └── SearchButton
│   └── UserMenu
│       ├── Avatar
│       └── Dropdown
├── ProductDetails
│   ├── ImageGallery
│   │   ├── MainImage
│   │   └── ThumbnailList
│   │       └── Thumbnail (×4)
│   ├── ProductInfo
│   │   ├── ProductTitle
│   │   ├── Rating
│   │   │   └── Star (×5)
│   │   ├── Price
│   │   └── Description
│   └── PurchasePanel
│       ├── QuantitySelector
│       ├── AddToCartButton
│       └── WishlistButton
├── Reviews
│   ├── ReviewSummary
│   └── ReviewList
│       └── ReviewCard (×many)
│           ├── UserInfo
│           ├── Rating
│           └── ReviewText
└── Footer
    ├── FooterLinks
    └── Copyright

Composition Best Practices

1. Keep Components Small

keep-small.jsx
// ❌ Too large
function ProductCard() {
  return (
    <div>
      {/* 100+ lines of JSX */}
    </div>
  )
}

// ✅ Split into smaller pieces
function ProductImage({ src, alt }) {
  return <img src={src} alt={alt} />
}

function ProductTitle({ children }) {
  return <h3>{children}</h3>
}

function ProductPrice({ price }) {
  return <p className="price">${price}</p>
}

function ProductCard({ product }) {
  return (
    <div className="card">
      <ProductImage src={product.image} alt={product.name} />
      <ProductTitle>{product.name}</ProductTitle>
      <ProductPrice price={product.price} />
      <AddToCartButton productId={product.id} />
    </div>
  )
}

// Rule of thumb: If a component is >100 lines, split it

2. Name Components Descriptively

descriptive-names.jsx
// ❌ Vague names
function Box() { }
function Item() { }
function Thing() { }

// ✅ Descriptive names
function UserProfileCard() { }
function ProductListItem() { }
function NavigationMenu() { }

3. Avoid Prop Drilling

avoid-drilling.jsx
// ❌ Prop drilling - passing props through many levels
function App() {
  const user = { name: 'Alice' }
  return <Layout user={user} />
}

function Layout({ user }) {
  return <Header user={user} />
}

function Header({ user }) {
  return <UserMenu user={user} />
}

function UserMenu({ user }) {
  return <div>{user.name}</div>
}

// ✅ Better solutions:
// 1. Composition - pass components, not data
function App() {
  const user = { name: 'Alice' }
  return (
    <Layout>
      <Header>
        <UserMenu user={user} />
      </Header>
    </Layout>
  )
}

// 2. Context (we'll learn this later)
// 3. State management libraries

4. Compose with Intention

compose-intention.jsx
// ❌ Random composition
function Page() {
  return (
    <div>
      <Button />
      <Card>
        <Header />
        <Input />
      </Card>
      <Footer />
    </div>
  )
}

// ✅ Logical, intentional composition
function Page() {
  return (
    <PageLayout>
      <Header />
      <MainContent>
        <Card>
          <Form>
            <Input />
            <Button>Submit</Button>
          </Form>
        </Card>
      </MainContent>
      <Footer />
    </PageLayout>
  )
}

// Clear hierarchy and relationships

5. Extract When You Repeat

extract-repetition.jsx
// ❌ Repetitive code
function Dashboard() {
  return (
    <div>
      <div className="stat-card">
        <h3>Users</h3>
        <p className="number">1,234</p>
      </div>
      <div className="stat-card">
        <h3>Revenue</h3>
        <p className="number">$45,678</p>
      </div>
      <div className="stat-card">
        <h3>Orders</h3>
        <p className="number">567</p>
      </div>
    </div>
  )
}

// ✅ Extract into reusable component
function StatCard({ title, value }) {
  return (
    <div className="stat-card">
      <h3>{title}</h3>
      <p className="number">{value}</p>
    </div>
  )
}

function Dashboard() {
  return (
    <div>
      <StatCard title="Users" value="1,234" />
      <StatCard title="Revenue" value="$45,678" />
      <StatCard title="Orders" value="567" />
    </div>
  )
}

Key Takeaways

  • Composition means building complex UIs from simple components
  • Each component should have a single responsibility
  • Build components from the bottom up (small to large)
  • Use props and children for customization and flexibility
  • Prefer composition over inheritance in React
  • Keep components small (under 100 lines when possible)
  • Separate container (logic) from presentational (display) components
  • Use layout components for consistent structure
  • Create specialized components from generic ones
  • Extract repetitive code into reusable components
  • Design component hierarchies before coding
  • Avoid prop drilling with composition or context
  • Name components descriptively based on what they do
  • Composition makes code more maintainable and testable

What's Next?

Congratulations! You've completed the Components Basics section. You now understand:

  • How to create function components
  • How to pass and use props
  • How to work with the children prop
  • How to destructure props for cleaner code
  • How to compose components into complex UIs

But there's still a big piece missing: your components are still static. They can't remember things or respond to user interactions. That's where state comes in!

In the next section, you'll learn about state - how to make your components interactive, dynamic, and truly alive. Get ready to build components that respond to clicks, remember user input, and update themselves! 🚀

Learning how to build complex UIs with component composition in React!

Previous
Props Destructuring
Next
Introduction to State

Never Miss a New React Tutorial

Join 2,000+ developers learning React step-by-step. Get new tutorials, tips, and exclusive resources delivered to your inbox - completely FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

React Tutorials

0 of 42 completed

Your Progress0%

Topics

Getting Started

  • What is React?
  • React vs Vanilla JavaScript
  • Setting Up Your Environment
  • Your First React App

JSX Fundamentals

  • Introduction to JSX
  • JSX Expressions and Variables
  • Conditional Rendering
  • Lists and Keys
  • Styling in JSX

Components Basics

  • Function Components
  • Props
  • Children Prop
  • Props Destructuring
  • Component Composition

State Management

  • Introduction to State
  • useState Hook
  • State Updates and Re-renders
  • Multiple State Variables
  • State Best Practices

Events and Interactivity

  • Handling Events
  • Event Objects
  • Forms in React
  • Form Validation

Side Effects and Data

  • Introduction to useEffect
  • Data Fetching
  • Cleanup Functions
  • Dependency Arrays

Advanced Hooks

  • useRef Hook
  • useContext Hook
  • useMemo Hook
  • useCallback Hook

React Patterns

  • Custom Hooks
  • Higher-Order Components
  • Render Props Pattern

React Router

  • Introduction to React Router
  • Routes and Navigation
  • Dynamic Routes and Parameters

Best Practices

  • Component Organization
  • Performance Optimization
  • Error Handling
  • Testing React Components

Real World Project

  • Building a Complete App
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo