Module 7: Advanced React Patterns

Learn advanced React patterns including compound components, render props, higher-order components, and custom hooks for building scalable applications.

Back to Course|6 hours|Advanced

Advanced React Patterns

Learn advanced React patterns including compound components, render props, higher-order components, and custom hooks for building scalable applications.

Progress: 0/4 topics completed0%

Select Topics Overview

Compound Components

Learn compound components pattern for creating flexible and reusable component APIs

Content by: Harsh Patel

MERN Stack Developer

Connect

What are Compound Components?

Compound components are a pattern where components are used together such that they share an implicit state that lets them communicate with each other. This pattern provides a flexible and intuitive API for complex components.

Basic Compound Components

Code Example
// Basic compound components example
import React, { createContext, useContext, useState } from 'react';

const TabsContext = createContext();

function Tabs({ children, defaultIndex = 0 }) {
    const [activeIndex, setActiveIndex] = useState(defaultIndex);

    return (
        <TabsContext.Provider value={{ activeIndex, setActiveIndex }}>
            <div className="tabs">
                {children}
            </div>
        </TabsContext.Provider>
    );
}

function TabList({ children }) {
    return (
        <div className="tab-list">
            {children}
        </div>
    );
}

function Tab({ index, children }) {
    const { activeIndex, setActiveIndex } = useContext(TabsContext);
    const isActive = index === activeIndex;

    return (
        <button
            className={`tab ${isActive ? 'active' : ''}`}
            onClick={() => setActiveIndex(index)}
        >
            {children}
        </button>
    );
}

function TabPanels({ children }) {
    return (
        <div className="tab-panels">
            {children}
        </div>
    );
}

function TabPanel({ index, children }) {
    const { activeIndex } = useContext(TabsContext);
    
    if (index !== activeIndex) return null;
    
    return (
        <div className="tab-panel">
            {children}
        </div>
    );
}

// Usage
function App() {
    return (
        <Tabs defaultIndex={0}>
            <TabList>
                <Tab index={0}>Home</Tab>
                <Tab index={1}>About</Tab>
                <Tab index={2}>Contact</Tab>
            </TabList>
            <TabPanels>
                <TabPanel index={0}>
                    <h2>Home Content</h2>
                    <p>Welcome to our website!</p>
                </TabPanel>
                <TabPanel index={1}>
                    <h2>About Content</h2>
                    <p>Learn more about us.</p>
                </TabPanel>
                <TabPanel index={2}>
                    <h2>Contact Content</h2>
                    <p>Get in touch with us.</p>
                </TabPanel>
            </TabPanels>
        </Tabs>
    );
}
Swipe to see more code

Advanced Compound Components

Code Example
// Advanced compound components with flexible API
import React, { createContext, useContext, useState, cloneElement, Children } from 'react';

const AccordionContext = createContext();

function Accordion({ children, multiple = false }) {
    const [openItems, setOpenItems] = useState(new Set());

    const toggleItem = (index) => {
        if (multiple) {
            const newOpenItems = new Set(openItems);
            if (newOpenItems.has(index)) {
                newOpenItems.delete(index);
            } else {
                newOpenItems.add(index);
            }
            setOpenItems(newOpenItems);
        } else {
            setOpenItems(new Set([openItems.has(index) ? null : index]));
        }
    };

    const isOpen = (index) => openItems.has(index);

    return (
        <AccordionContext.Provider value={{ toggleItem, isOpen }}>
            <div className="accordion">
                {Children.map(children, (child, index) => 
                    cloneElement(child, { index })
                )}
            </div>
        </AccordionContext.Provider>
    );
}

function AccordionItem({ index, children }) {
    const { toggleItem, isOpen } = useContext(AccordionContext);
    const open = isOpen(index);

    return (
        <div className={`accordion-item ${open ? 'open' : ''}`}>
            {Children.map(children, child => 
                cloneElement(child, { index, open, toggleItem })
            )}
        </div>
    );
}

function AccordionTrigger({ index, children, open, toggleItem }) {
    return (
        <button
            className="accordion-trigger"
            onClick={() => toggleItem(index)}
        >
            {children}
            <span className={`arrow ${open ? 'up' : 'down'}`}>ā–¼</span>
        </button>
    );
}

function AccordionContent({ open, children }) {
    return (
        <div className={`accordion-content ${open ? 'open' : ''}`}>
            {children}
        </div>
    );
}

// Usage
function App() {
    return (
        <Accordion multiple>
            <AccordionItem>
                <AccordionTrigger>Section 1</AccordionTrigger>
                <AccordionContent>
                    <p>Content for section 1</p>
                </AccordionContent>
            </AccordionItem>
            <AccordionItem>
                <AccordionTrigger>Section 2</AccordionTrigger>
                <AccordionContent>
                    <p>Content for section 2</p>
                </AccordionContent>
            </AccordionItem>
        </Accordion>
    );
}
Swipe to see more code

šŸŽÆ Practice Exercise

Test your understanding of this topic:

Additional Resources

šŸ“š Recommended Reading

  • •React Design Patterns
  • •Advanced React Patterns
  • •Custom Hooks Best Practices

🌐 Online Resources

  • •Compound Components Tutorial
  • •Render Props Guide
  • •HOC Patterns Examples

Ready for the Next Module?

Continue your learning journey and master the next set of concepts.

Continue to Module 8