Extend Functional Components in ReactJS

While working on a React project for a U.S.-based analytics dashboard, I needed to reuse a few UI components with slightly different behaviors.

At first, I thought of duplicating the component and tweaking it, but that quickly became messy. That’s when I explored ways to extend functional components in ReactJS, and it made my workflow much cleaner.

In this tutorial, I’ll show you how I extend functional components in React using composition, higher-order components (HOCs), and custom hooks. These methods help you write cleaner, reusable, and maintainable React code.

What Does It Mean to Extend a Functional Component?

In React, “extending” a component doesn’t mean inheritance (like in class-based components). Instead, it means reusing and enhancing an existing component’s logic or UI without rewriting it.

Functional components rely on composition; you build complex UIs by combining smaller, reusable pieces.

For example, you might want to:

  • Add logging or analytics to an existing component.
  • Reuse a button with different colors and behaviors.
  • Wrap a component to handle API loading states.

Let’s look at a few practical methods I use.

Method 1 – Extend Functional Components Using Composition

Composition is the most common and React-friendly way to extend functionality. It involves wrapping components inside others.

Here’s a simple example I used in my project to extend a Card component.

Example: Base Card Component

// Card.js
import React from 'react';

const Card = ({ title, children }) => {
  return (
    <div style={{
      border: '1px solid #ccc',
      borderRadius: '8px',
      padding: '16px',
      margin: '10px',
      boxShadow: '0 2px 5px rgba(0,0,0,0.1)'
    }}>
      <h3>{title}</h3>
      <div>{children}</div>
    </div>
  );
};

export default Card;

You can refer to the screenshot below to see the output

Extend Functional Components ReactJS

Example: Extended Card with Footer

Now let’s extend this Card to include a footer message.

// InfoCard.js
import React from 'react';
import Card from './Card';

const InfoCard = ({ title, children, footer }) => {
  return (
    <Card title={title}>
      {children}
      {footer && (
        <div style={{ marginTop: '10px', fontSize: '0.9em', color: '#555' }}>
          {footer}
        </div>
      )}
    </Card>
  );
};

export default InfoCard;

Method 2 – Extend Functional Components Using Higher-Order Components (HOCs)

A Higher-Order Component (HOC) is a function that takes a component and returns a new one. It’s great for adding common logic like authentication, logging, or analytics.

Here’s how I used an HOC to add logging to multiple components.

Example: HOC for Logging

// withLogger.js
import React, { useEffect } from 'react';

const withLogger = (WrappedComponent, componentName) => {
  return (props) => {
    useEffect(() => {
      console.log(`${componentName} mounted`);
      return () => console.log(`${componentName} unmounted`);
    }, []);

    return <WrappedComponent {...props} />;
  };
};

export default withLogger;

Example: Using the HOC

// Dashboard.js
import React from 'react';
import withLogger from './withLogger';

const Dashboard = () => {
  return <h2>Welcome to the Analytics Dashboard</h2>;
};

export default withLogger(Dashboard, 'Dashboard');

You can refer to the screenshot below to see the output

Extend Functional Components in ReactJS

When the Dashboard component mounts or unmounts, it logs messages to the console. You can reuse withLogger across multiple components without repeating code.

Method 3 – Extend Functional Components Using Custom Hooks

Custom hooks are another great way to extend functionality, especially logic-based features like fetching data, handling forms, or managing local storage.

Here’s how I extended a component to handle API calls using a custom hook.

Example: Custom Hook for Fetching Data

// useFetch.js
import { useState, useEffect } from 'react';

const useFetch = (url) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url)
      .then((res) => res.json())
      .then((data) => {
        setData(data);
        setLoading(false);
      })
      .catch(() => setLoading(false));
  }, [url]);

  return { data, loading };
};

export default useFetch;

Example: Use the Custom Hook

// UsersList.js
import React from 'react';
import useFetch from './useFetch';

const UsersList = () => {
  const { data, loading } = useFetch('https://jsonplaceholder.typicode.com/users');

  if (loading) return <p>Loading users...</p>;

  return (
    <ul>
      {data.map((user) => (
        <li key={user.id}>{user.name} — {user.email}</li>
      ))}
    </ul>
  );
};

export default UsersList;

You can refer to the screenshot below to see the output

ReactJS Extend Functional Components

The useFetch hook can now be used in any component that needs data fetching, making your code more modular and testable.

Method 4 – Extend Functional Components with Props

Sometimes, the simplest way to “extend” a component is just to pass additional props that modify its behavior.

Example: Configurable Button Component

// Button.js
import React from 'react';

const Button = ({ label, color = 'blue', onClick }) => {
  return (
    <button
      onClick={onClick}
      style={{
        backgroundColor: color,
        color: 'white',
        padding: '10px 16px',
        border: 'none',
        borderRadius: '5px',
        cursor: 'pointer'
      }}
    >
      {label}
    </button>
  );
};

export default Button;

Usage Example

// App.js
import React from 'react';
import Button from './Button';

function App() {
  return (
    <div style={{ padding: '20px' }}>
      <Button label="Save Report" color="green" onClick={() => alert('Report saved!')} />
      <Button label="Delete Report" color="red" onClick={() => alert('Report deleted!')} />
    </div>
  );
}

export default App;

This approach keeps one core component (Button) flexible enough to handle multiple use cases through props, no duplication needed.

Best Practices When Extending Functional Components

Here are some lessons I’ve learned over the years:

  • Prefer composition over inheritance. React’s design philosophy encourages composition.
  • Use HOCs and hooks for logic reuse. Keep UI and logic separate.
  • Keep components small and focused. Each should do one thing well.
  • Avoid prop drilling. Use context or hooks to share state across components.

When I first started extending functional components, I tried to mimic class inheritance. It worked, but the code was hard to maintain. Once I switched to composition and hooks, everything became cleaner and easier to debug.

These techniques not only make your React apps more scalable but also align with modern React best practices.

You may read:

Leave a Comment

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.