React Component Reuse

I have seen many projects turn into a “spaghetti code” nightmare because developers didn’t plan for reuse.

I remember working on a massive fintech dashboard for a New York investment firm where we had six different versions of the same button.

It was a maintenance disaster. Every time the branding changed, we had to hunt down every single instance to update the hex codes.

Since then, I have refined my approach to building reusable components. It saves time, reduces bugs, and makes the codebase much easier to navigate.

In this tutorial, I will share the best practices I use daily to create flexible and scalable React components.

1. Use Composition Over Inheritance

One of the most powerful patterns I use is component composition. Instead of creating complex props to toggle features, I wrap components inside one another.

Think of a “Health Insurance Plan” card used in a US-based HR portal. You might want the same layout but different internal content for Dental vs. Vision plans.

Here is how I structured this for a recent client:

import React from 'react';

// The base Layout component
const InsuranceCard = ({ title, children, footerAction }) => {
  return (
    <div style={{ border: '1px solid #ddd', borderRadius: '8px', padding: '20px', width: '300px' }}>
      <h2 style={{ fontSize: '1.2rem', color: '#004a99' }}>{title}</h2>
      <div className="card-content" style={{ margin: '15px 0' }}>
        {children}
      </div>
      <button 
        onClick={footerAction}
        style={{ backgroundColor: '#007bff', color: 'white', border: 'none', padding: '10px', borderRadius: '4px', cursor: 'pointer' }}
      >
        Select Plan
      </button>
    </div>
  );
};

// Reusing the base in a specific context
const EnrollmentPage = () => {
  const handleEnroll = (plan) => alert(`Enrolled in ${plan}`);

  return (
    <div style={{ display: 'flex', gap: '20px' }}>
      <InsuranceCard 
        title="PPO Gold Plan" 
        footerAction={() => handleEnroll('PPO Gold')}
      >
        <p>Annual Deductible: $1,500</p>
        <p>Out-of-Pocket Max: $4,000</p>
        <ul style={{ fontSize: '0.9rem' }}>
          <li>Primary Care: $25 Copay</li>
          <li>Specialist: $50 Copay</li>
        </ul>
      </InsuranceCard>

      <InsuranceCard 
        title="HSA Bronze Plan" 
        footerAction={() => handleEnroll('HSA Bronze')}
      >
        <p>Annual Deductible: $6,000</p>
        <p>Employer Contribution: $1,000</p>
        <p style={{ fontStyle: 'italic' }}>Tax-advantaged savings included.</p>
      </InsuranceCard>
    </div>
  );
};

export default EnrollmentPage;

You can see the output in the screenshot below.

Component Reuse React

I prefer this because the InsuranceCard doesn’t need to know about “Deductibles” or “Copays.” It just provides the shell.

2. Implement Custom Hooks for Logic Reuse

Early in my career, I used to duplicate “Fetching” logic in every component. Now, I always extract shared logic into Custom Hooks.

Imagine a real estate app listing homes in Texas and Florida. Both lists need to fetch data from an API and handle “Loading” states.

I use a custom hook to keep the UI components clean and focused only on the visuals.

import { useState, useEffect } from 'react';

// Custom Hook for fetching property data
const usePropertyData = (stateCode) => {
  const [properties, setProperties] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // Simulating an API call to a US Real Estate Database
    const fetchListings = async () => {
      setLoading(true);
      try {
        // In a real app: fetch(`https://api.us-homes.com/v1/listings?state=${stateCode}`)
        setTimeout(() => {
          const mockData = [
            { id: 1, address: "123 Maple St, Austin, TX", price: "$450,000" },
            { id: 2, address: "456 Palm Ave, Miami, FL", price: "$620,000" }
          ].filter(item => item.address.includes(stateCode));
          
          setProperties(mockData);
          setLoading(false);
        }, 1000);
      } catch (error) {
        console.error("Failed to fetch listings", error);
        setLoading(false);
      }
    };

    fetchListings();
  }, [stateCode]);

  return { properties, loading };
};

// Reusable Component using the Hook
const PropertyList = ({ stateName, stateCode }) => {
  const { properties, loading } = usePropertyData(stateCode);

  if (loading) return <p>Searching current listings in {stateName}...</p>;

  return (
    <div>
      <h3>Available Homes in {stateName}</h3>
      {properties.length > 0 ? (
        <ul>
          {properties.map(p => (
            <li key={p.id}>{p.address} - <strong>{p.price}</strong></li>
          ))}
        </ul>
      ) : (
        <p>No listings found in {stateCode}.</p>
      )}
    </div>
  );
};

export default PropertyList;

You can see the output in the screenshot below.

Component Reuse in React

This pattern allows me to use the same usePropertyData hook in a map view, a list view, or even a search bar without rewriting a single line of logic.

3. Create a Flexible Theme with CSS Variables

When building for a wide audience in the US, accessibility and “Dark Mode” are essential. I never hardcode colors inside my components anymore.

Instead, I pass a “theme” prop or use CSS variables. This ensures that a “Submit” button looks consistent whether it’s on a government portal or a retail site.

import React from 'react';

const PrimaryButton = ({ label, variant = 'primary', onClick }) => {
  const styles = {
    primary: { backgroundColor: '#003366', color: '#ffffff' }, // Federal Blue
    secondary: { backgroundColor: '#f4f4f4', color: '#333333' }, // Neutral Gray
    danger: { backgroundColor: '#d32f2f', color: '#ffffff' }   // Error Red
  };

  const currentStyle = styles[variant] || styles.primary;

  return (
    <button 
      onClick={onClick}
      style={{
        ...currentStyle,
        padding: '12px 24px',
        fontSize: '16px',
        fontWeight: 'bold',
        borderRadius: '5px',
        border: 'none',
        cursor: 'pointer',
        boxShadow: '0 2px 4px rgba(0,0,0,0.2)'
      }}
    >
      {label}
    </button>
  );
};

// Usage in an IRS-style Tax Form Example
const TaxForm = () => {
  return (
    <div style={{ padding: '40px' }}>
      <h1>Form 1040 - U.S. Individual Income Tax Return</h1>
      <p>Ensure all fields are filled before submitting to the IRS.</p>
      
      <div style={{ display: 'flex', gap: '15px' }}>
        <PrimaryButton label="Submit Return" variant="primary" onClick={() => alert('Submitted')} />
        <PrimaryButton label="Save Draft" variant="secondary" onClick={() => alert('Saved')} />
        <PrimaryButton label="Discard" variant="danger" onClick={() => alert('Cleared')} />
      </div>
    </div>
  );
};

export default TaxForm;

You can see the output in the screenshot below.

React Component Reuse

By defining variants like “primary” or “danger,” I can change the entire app’s look by editing one object instead of 50 files.

4. Use the Render Props Pattern

Sometimes you need a component to handle the logic, but let the user decide how the UI looks. This is common in complex data tables or “Search” filters.

I use Render Props when I want to build a reusable “State Selector” for US shipping addresses, where the display might differ between a mobile app and a desktop site.

import React, { useState } from 'react';

// Logic component: Handles selecting a US state
const StateSelector = ({ render }) => {
  const [selectedState, setSelectedState] = useState('NY');
  const states = [
    { code: 'NY', name: 'New York' },
    { code: 'CA', name: 'California' },
    { code: 'TX', name: 'Texas' },
    { code: 'FL', name: 'Florida' }
  ];

  return render({
    states,
    selectedState,
    onSelect: (code) => setSelectedState(code)
  });
};

// Usage 1: A simple dropdown for a Shipping Form
const ShippingForm = () => (
  <StateSelector 
    render={({ states, selectedState, onSelect }) => (
      <div>
        <label>Select Shipping State: </label>
        <select value={selectedState} onChange={(e) => onSelect(e.target.value)}>
          {states.map(s => <option key={s.code} value={s.code}>{s.name}</option>)}
        </select>
        <p>Current Tax Rate for {selectedState}: {selectedState === 'NY' ? '8.875%' : '6.25%'}</p>
      </div>
    )}
  />
);

// Usage 2: A modern "Card" layout for a Travel Guide
const TravelGuide = () => (
  <StateSelector 
    render={({ states, onSelect }) => (
      <div style={{ display: 'flex', gap: '10px', marginTop: '20px' }}>
        {states.map(s => (
          <div 
            key={s.code} 
            onClick={() => onSelect(s.code)}
            style={{ padding: '10px', border: '2px solid blue', cursor: 'pointer' }}
          >
            Explore {s.name}
          </div>
        ))}
      </div>
    )}
  />
);

This pattern is a lifesaver when you have a specific logic that must remain consistent, but the UI requirements are highly volatile.

5. Destructure Props for Scalability

One mistake I often see is passing a giant “user” object into a component. This makes it hard to reuse the component for a “guest” or an “admin.”

I always destructure props. If a component only needs a zipCode, only pass the zipCode, not the entire address object.

import React from 'react';

// Good: Only takes exactly what it needs
const WeatherWidget = ({ cityName, temperature, unit = 'F' }) => {
  return (
    <div style={{ background: '#f0f8ff', padding: '15px', borderRadius: '10px', width: '200px' }}>
      <h4>{cityName}</h4>
      <p style={{ fontSize: '24px', fontWeight: 'bold' }}>
        {temperature}°{unit}
      </p>
      <p>{temperature > 80 ? 'Pack Sunscreen ☀️' : 'Grab a Jacket 🧥'}</p>
    </div>
  );
};

// Implementation for different US cities
const Dashboard = () => {
  return (
    <div style={{ display: 'flex', gap: '20px' }}>
      {/* Reusing for Chicago */}
      <WeatherWidget cityName="Chicago, IL" temperature={32} />
      
      {/* Reusing for Phoenix */}
      <WeatherWidget cityName="Phoenix, AZ" temperature={102} />
      
      {/* Reusing for a custom Celsius display in a Science Lab app */}
      <WeatherWidget cityName="Seattle, WA" temperature={15} unit="C" />
    </div>
  );
};

export default Dashboard;

You can see the output in the screenshot below.

Component React Reuse

By keeping the props flat and simple, you make it much easier for other developers on your team to understand how to use your component.

6. Higher-Order Components (HOC) for Authentication

In many US enterprise apps, certain features must be hidden based on the user’s clearance or subscription level (e.g., “Premium” vs “Basic” accounts).

I use HOCs to wrap components with “Permission” logic so I don’t have to write if (user.isAdmin) inside every single UI component.

import React from 'react';

// The Higher Order Component
const withSubscriptionCheck = (WrappedComponent) => {
  return (props) => {
    // In a real app, this comes from a Global State or Context
    const user = { isPremium: false, name: "John Doe" };

    if (!user.isPremium) {
      return (
        <div style={{ padding: '20px', border: '1px solid red', color: 'red' }}>
          <strong>Access Denied:</strong> This feature requires a Premium USA-Gold Subscription.
        </div>
      );
    }

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

// A standard component for Stock Market Analysis
const StockAnalyzer = () => (
  <div>
    <h3>Real-time NASDAQ Insights</h3>
    <p>Detailed analysis of Apple (AAPL) and Microsoft (MSFT)...</p>
  </div>
);

// Creating the protected version
const ProtectedStockAnalyzer = withSubscriptionCheck(StockAnalyzer);

const App = () => {
  return (
    <div style={{ padding: '30px' }}>
      <h1>Wall Street Data Portal</h1>
      <ProtectedStockAnalyzer />
    </div>
  );
};

export default App;

This keeps my business logic separated from my presentation layer, which is a key principle of high-quality React development.

7. Use PropTypes and Default Values

As a project grows, it is easy to forget what data a component expects. This leads to the dreaded “Cannot read property of undefined” error.

I always define defaultProps and use PropTypes (or TypeScript) to document my components. This acts as a manual for anyone else using my code.

import React from 'react';
import PropTypes from 'prop-types';

const USAddressDisplay = ({ street, city, state, zipCode, country }) => {
  return (
    <address style={{ fontStyle: 'normal', lineHeight: '1.6', borderLeft: '4px solid #ccc', paddingLeft: '10px' }}>
      <div>{street}</div>
      <div>{city}, {state} {zipCode}</div>
      <div>{country}</div>
    </address>
  );
};

// Defining default values for reuse
USAddressDisplay.defaultProps = {
  country: 'United States',
  state: 'NY'
};

// Documenting expected types
USAddressDisplay.propTypes = {
  street: PropTypes.string.isRequired,
  city: PropTypes.string.isRequired,
  state: PropTypes.string,
  zipCode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  country: PropTypes.string
};

// Usage
const ContactPage = () => (
  <div style={{ padding: '20px' }}>
    <h2>Corporate Headquarters</h2>
    <USAddressDisplay 
      street="1230 Avenue of the Americas" 
      city="New York" 
      zipCode="10020" 
    />
  </div>
);

export default ContactPage;

This prevents the app from crashing if a piece of data is missing and makes the code self-documenting for the rest of the team.

Using these strategies has made my life as a developer much easier over the years. It allows me to build faster and with much more confidence.

I hope you found these methods helpful! Try implementing just one of these in your next project, and you will see an immediate improvement in your code quality.

You may also like to read:

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.