Type to generate UI components from text

OR

Browse thousands of MUI, Tailwind, React components that are fully customizable and responsive.

Explore Components

Best Practices on How to Build React Reusable Components

Reusable components play a very vital role in React. They make it very easy for you to use an already-created component across several other components in your code or application.

Sometimes developers tend to keep repeating the same lines of code they used in styling a UI over and over throughout different components. This isn’t bad, but it makes your code base look overloaded, and most times it is difficult to read and explain by other fellow developers.

Also, reusable components will save you a lot of time when you are creating a template, testing your application, and updating your code in the future.

In this article, learn what React reusable components are and the best practices for building React reusable components.

Purecode AI is an innovative AI assistant that can generate thousands of custom HTML, CSS, and JavaScript components for web development. It provides an extensive library of responsive, pre-made components that come with default styling out of the box. You can easily customize these components by tweaking colors, spacing, paddings, and more to match their brand design needs.

The key advantage of Purecode AI is its ability to generate not just the component markup, but also the accompanying CSS styles and JavaScript interactivity required to build fully-functional components. This saves you an immense amount of time compared to starting from scratch. With its intelligent AI assistant and vast component library, Purecode AI is the future of efficient, customizable web development.

Purecode AI homepage

Let’s dive right in 🚀

Reusable Components in React

Reusable components in React are UIs that perform a specific function and found in various parts of an application to create more user interfaces (UIs).

These components consist typically of both JavaScript and JSX markup and can range from simple presentational components like the styling of buttons, forms, links, etc to more complex, container components that manage state and behavior.

Benefits of Reusable Components

  • Time management and efficiency: Reusable components in React are essential for time management and efficiency. This is because reusable components speed up the rate of development, making it easy for you as a developer to reuse an already existing UI in your application and make you more productive.

  • Consistency: Reusable components in React promote a consistent user interface across all components in an application this helps you create a consistent code pattern that is easy to read and understand.

  • Maintainability: Without maintenance in mind, a react application is likely to shut down over time. Reusable components make it very easy and effective to maintain a React application as the codebase can be read, understood, and updated over time.

Three Indicators of a Reusable React Component

  • Repetitive creation of wrappers with the same CSS style: Reusable components are not only written in JavaScript codes alone, you can also reuse a CSS code that you used in styling a particular component for other components. This is common in situations when you style a button element. You can use the same style for other button components by wrapping the style together and applying it to other button elements.

  • Repetitive use of event listeners: Instead of creating repetitive event listeners across multiple components in a react application, you can create a reusable component that performs a specific task of taking action whenever a button is clicked or if a form is submitted. This ensures readability and consistency in your code base.

  • Repetitive use of the same GraphQL script: GraphQL is a query language for APIs which makes the process of data fetching easy. The use of reusable components in GraphQL scripts ensures the understandability and maintainability of the code base when needed.

Best Practices for Building Reusable Components

Passing Data Through Props

Props are read-only components or parameters passed into React components, which allow users to pass arguments or data from a parent component to its children. Making use of props helps developers create versatile, reusable, and more dynamic property components in various situations.

Button Component

You can choose to make your button component a reusable component so that you don’t have to start all over again to style the button tag.

Here is how to achieve this;

At this point, you must have installed react into your project, if not, visit the react website. After installing react into your project, in your component folder, create a file with any name of your choice but for the sake of this article you can make use of Button.js and then write;

// ./components/Button.js
import React, { useState } from "react";

function Button(props) {
  const [width] = useState(props.size);
  const [variant] = useState(props.variant);

  const buttonDisplay = {
    border: "none",
    borderRadius: "10px",
    fontSize: "16px",
    color: "#fff",
    backgroundColor: "#54a0ff",
    cursor: "pointer",
  };

  if (props.size === "lg") {
    buttonDisplay.height = "50px";
    buttonDisplay.width = "200px";
    buttonDisplay.fontSize = "22px";
  } else if (props.size === "sm") {
    buttonDisplay.height = "50px";
    buttonDisplay.width = "100px";
    buttonDisplay.fontSize = "12px";
  }

  return (
    <button type={props.type} onClick={props.onClick} style={buttonDisplay}>
      {props.children}
    </button>
  );
}

export default Button;

The code above is an example of a functional component and accepts an argument of props. A state hook (useState) is declared with two state variables of width and variant which are initialized with the value of props.size and props.variant.buttonDisplay assigns preferred styles to the button element. Lastly, a conditional statement is added.

After writing the above code in your button.js file, you can go further to import and reuse this button component in your App.js file or any other file you would want to apply the style.

Here is how to go about these:

// App.js
import React from "react";
import "./App.css";
import Button from "./components/Button";

function App() {
  const handleClick = () => {
    console.log("Button clicked!");
  };

  return (
    <div className="App">
      <header className="App-header">
        <h1>Reusable Button Component Example</h1>

        <Button type="button" size="lg" onClick={handleClick}>
          Click me!
        </Button>
        <br />
        <Button type="button" size="sm" onClick={handleClick}>
          Click me too!
        </Button>
      </header>
    </div>
  );
}

export default App;

Here is how the code above looks on the webpage;

Button components

Set Default Props for Optional Props

The defaultProps property is a static React component property that allows you to set default values for the props argument.

You can go about setting default values for optional props using the defaultProps property of the component.

Here is how you can set default props in your button component;

import React, { useState } from "react";

function Button(props) {
  const { type, onClick, size } = props;

  const [buttonDisplay] = useState({
    border: "none",
    borderRadius: "10px",
    fontSize: "16px",
    color: "#fff",
    backgroundColor: "#54a0ff",
    cursor: "pointer",
    height: "",
  });

  if (size === "lg") {
    buttonDisplay.height = "50px";
    buttonDisplay.width = "200px";
    buttonDisplay.fontSize = "22px";
  } else if (size === "sm") {
    buttonDisplay.height = "50px";
    buttonDisplay.width = "100px";
    buttonDisplay.fontSize = "12px";
  }

  return (
    <button type={type} onClick={onClick} style={buttonDisplay}>
      {props.children}
    </button>
  );
}

Button.defaultProps = {
  type: "button",
  onClick: () => {},
  size: "md",
};

export default Button;

Default props are useful when a component has optional props that, when using a component, may not always be provided. Therefore using defaultProps allows you to set a default value when a specific prop value is not set to an element. Example is the image below.

Button components

Make Your Props Immutable

The immutability of props in React means that once the value of a parent component is set, the children component cannot alter or modify it. The immutability of props is important for several reasons which include;

  • By making your props immutable, you ensure a predictable data flow. This means that the immutability of props ensures the consistent and predictable passing of data from the parent component down to the child components thereby reducing the chances of unexpected behavior.

  • Immutability of props makes your debugging process easy because you can easily locate where an error is coming from and make necessary corrections to it.

  • Immutability of props helps you in maintaining your react component. It helps you minimize the rate of unexpected side effects from your code.

In React, it is not advisable that you modify a props component. Doing this might cause some unexpected side effects such as;

  • Modifying props makes debugging difficult as you might not find out easily where an error might be coming from.

  • Modifying props makes it difficult to maintain your codebase.

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

function Button(props) {
  const { type, onClick, size, children } = props;

  const buttonDisplay = {
    border: 'none',
    borderRadius: '10px',
    fontSize: '16px',
    color: '#fff',
    backgroundColor: '#54a0ff',
    cursor: 'pointer',
    height: size === 'lg' ? '50px' : size === 'sm' ? '14px' : '',
    fontSize: size === 'lg' ? '22px' : size === 'sm' ? '12px' : '',
  };

  return (
    <button type={type} onClick={onClick} style={buttonDisplay}>
      {children}
    </button>
  );
}

Button.propTypes = {
  type: PropTypes.oneOf(['button', 'submit']),
  onClick: PropTypes.func.isRequired,
  size: PropTypes.oneOf(['sm', 'md', 'lg']),
  children: PropTypes.node.isRequired,
};

Button.defaultProps = {
  type: 'button',
  size: 'md',
};

export default Button;

The code above is an example of how to make use of the defaultProps in styling your button component. You make use of PropTypes to define a props type which in the example is restricted to a set value of button, submit. You use defaultProps to specify default values when a specific props has not yet been set to an element. This can be seen in Button.defaultProps where the default type is set to a default button and size is set to a default of md.

Localize the Styles for Your Components

In React, there are different methods that you can make use of in styling your application. You can either make use of the inline styling method where you add your CSS styles in the same template as your react components. You can also make use of the CSS Modules. The CSS modules mean you are importing styles from the CSS module component to your react Application.

Using the Inline Styling Method

Styling your react application with the inline method is the most common method. In this method, the CSS styles are written as a regular Javascript object, therefore, you are not allowed to write things in the original way you are used to when using the normal CSS but instead, you have to wrap this CSS command into quotes to make it a valid JS property or use the camel casing notation i.e maxWidth, fontSize, backgroundColor etc.

It is important that you style your React application properly to prevent conflicts between two elements. This mostly occurs in situations when your code base looks overloaded or when you make use of one class name in styling components. This in turn can lead to poor readability and maintainability of your code.

Here is an example of how to style a TextInput component with inline styles.

import React from "react";

function Form({ onChange, values }) {
  const inputStyle = {
    padding: "8px 12px",
    fontSize: "16px",
    border: "1px solid #ccc",
    borderRadius: "4px",
    width: "100%",
    marginBottom: "10px",
  };

  return (
    <div>
      <input
        type="text"
        placeholder="Username"
        onChange={onChange}
        value={values.username}
        style={inputStyle}
      />
      <input
        type="email"
        placeholder="Your email address"
        onChange={onChange}
        value={values.email}
        style={inputStyle}
      />
      <input
        type="password"
        placeholder="Password (not less than ten letters)"
        onChange={onChange}
        value={values.password}
        style={inputStyle}
      />
    </div>
  );
}

export default Form;

Using the CSS Module Method

Here is an example of how to style a TextInput component with CSS Module.

// Form.js
import React from 'react';
import styles from './Form.module.css';

function TextInput({ placeholder, onChange, value }) {
  return (
    <input
      type="text"
      placeholder={placeholder}
      onChange={onChange}
      value={value}
      className={styles.input}
    />
  );
}

export default TextInput;

for the CSS file;

/* Form.module.css */
.input {
  padding: 8px 12px;
  font-size: 16px;
  border: 1px solid #ccc;
  border-radius: 4px;
  width: 100%;
}

This is the result of the codes above;

Input Field

Custom Hooks

Creating custom hooks in React is very important as they can put together logic and state management into one component and reused across multiple components in your React application.

Custom Hooks enhance re-usability because you can make use of the custom hook you created in one component for all other components in your react application.

The YouTube video below will help you learn how you can create Custom Hooks.

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

function User({ userId }) {
  const [user, setUser] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUser = async () => {
      setIsLoading(true);
      try {
        const response = await fetch(`Input the API link${userId}`);
        if (!response.ok) {
          throw new Error('Failed to fetch user');
        }
        const userData = await response.json();
        setUser(userData);
      } catch (error) {
        setError(error);
      } finally {
        setIsLoading(false);
      }
    };

    fetchUser();

    return () => {

    };
  }, [userId]);

  return { user, isLoading, error };
}

export default User;

From the code above, we create a functional component User which takes in a parameter of userId and returns a state object of user, isLoading, and error. In the useEffect hook, it creates a custom hook fetchUser, which fetches user data from an API based on the provided userId.

// ./components/UserDetails.js
import React from 'react';
import FetchUser from './FetchUser';

function UserDetails({ userId }) {
  const { user, isLoading, error } = FetchUser({ userId });

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  if (!user) {
    return <div>User not found</div>;
  }

  return (
    <div>
      <h2>User Details</h2>
      <p>Name: {user.name}</p>
      <p>Email: {user.email}</p>
      <p>Password: {user.password}</p>
    </div>
  );
}

export default UserDetails;

From the code above, the FetchUser is a custom hook that fetches user data and the UserDetails components use this custom hook to display the user information.

Reusable Input Component

In a situation where your react application consists of various input fields, you can create a reusable input component and apply it to other input fields found in your application.

Here is an example of how you can create a reusable input component.

//.components/forms
import React from 'react';
import PropTypes from 'prop-types';

function Forms ({ type, placeholder, value, onChange }) {
  return (
    <div>
      <input
        type={text}
        placeholder={username}
        value={value}
        onChange={onChange}
    />

    <input
      type={email}
      placeholder={Input your email address}
      value={value}
      onChange={onChange}
    />

    <input
      type={password}
      placeholder={Input your password address}
      value={value}
      onChange={onChange}
    />

    </div>
  );
};

export default TextInput;

With the code above, you do not have to go through the stress of creating a fresh input field but instead, you can import this already created input field to any component of your choice.

Reusable Table Component

Tables are an extremely useful tool for displaying large sets of data. Most web applications make use of this method to display large sets of data on their web page. Creating a dynamic and reusable table component is very important as it helps your code to be reusable for any other components and as well easy to maintain.

You can fetch data asynchronously and display them on your table component. You can learn how to go about fetching data asynchronously through the YouTube video below:

Here is an example of how table is created for TableHeader and TableData components

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

function Table({ headers, data }) {
  return (
    <table>
      <thead>
        <tr>
          {headers.map((header, index) => (
            <th key={index}>{header}</th>
          ))}
        </tr>
      </thead>
      <tbody>
        {data.map((row, rowIndex) => (
          <tr key={rowIndex}>
            {row.map((cell, cellIndex) => (
              <td key={cellIndex}>{cell}</td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
};

export default Table;

for TableHeader component;

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

function TableHeader({ headers }) {
  return (
    <thead>
      <tr>
        {headers.map((header, index) => (
          <th key={index}>{header}</th>
        ))}
      </tr>
    </thead>
  );
};

export default TableHeader;

For TableData components

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

function TableData({ data }) {
  return (
    <tbody>
      {data.map((row, rowIndex) => (
        <tr key={rowIndex}>
          {row.map((cell, cellIndex) => (
            <td key={cellIndex}>{cell}</td>
          ))}
        </tr>
      ))}
    </tbody>
  );
};
export default TableData;

The code above is a functional component that takes in two props which are headers and data. The TableHeader component takes in the headers properties and renders it to the header row of the table. The TableData component is a functional component that takes in the data properties and renders it in the rows section of the table element.

Table Component

FAQs

What are reusable components and why build them?

Reusable components are self-contained pieces of UI logic and markup that we reuse across an application. Building reusable components improves code quality and saves development time by preventing duplicate code.

What are some best practices for building reusable React components?

  • Pass data into components via props rather than hard-coding values

  • Set defaultProps for optional props to handle missing values

  • Treat props as immutable within components to prevent bugs

  • Encapsulate styles locally within components for maintainability

  • Use the container/presentational pattern to separate logic and UI

  • Leverage custom hooks to extract reusable data fetching logic

How do you make React components reusable?

  • Build small, focused components that do one thing well

  • Accept data through props rather than hardcoding values

  • Give components a clear and descriptive name

  • Document components with PropTypes for clarity

  • Avoid complex logic and side effects within components

What is an example of a reusable React component?

Some common examples are buttons, inputs, tables, modals, and loading indicators. We can reuse these generic UI elements across an app.

How do you create a reusable form component in React?

  • Build a component that renders a <form> element

  • Accept the form fields and attributes as props

  • Manage form state with hooks like useState

  • Pass form submission handler as a prop

  • Wrap in Formik or React Hook Form for more functionality

How do you create a reusable table component in React?

  • Component accepts row data, column headers, and other props

  • Render a <table> with passed data

  • Allow column headers and row formatting customization

  • Paginate/filter/sort data for reusability

  • Export table component and reuse by passing different data

Tabular Comparison of Best Practices For Building Reusable React Components

Best PracticeDescriptionBenefits
Pass Data via PropsPass data into components through props rather than hardcoding dataMakes components more flexible and reusable
Set Default PropsSet default values for optional props with defaultPropsEnsures component renders properly if props not passed
Immutable PropsTreat props passed into a component as immutable – don’t modify themAvoids bugs and unexpected behavior
Localize StylesKeep all styles for a component in the same fileEasier to maintain styles and avoid affecting other components
Container/PresentationalSeparate container components (data/logic) from presentational (UI)Improved separation of concerns and reusability
Custom HooksExtract data fetching/logic into custom hooksFurther improves separation of concerns and encapsulation

Some key points of comparison:

  • Passing data via props vs hard-coding makes components more reusable

  • Default props provide fallback values for flexibility

  • Immutable props prevent bugs from unexpected mutations

  • Local styles keep changes isolated whereas global styles affect everything

  • Container/presentational and custom hooks encapsulate logic from UI

What You Have Learned

Reusable components play a very vital role in React as they make it very easy for you to use an already created component across several other components in your code or application. Reusable components in React are UIs that perform a specific function and used in various parts of an application to create more user interfaces (UIs).

Furthermore, the Immutability of props in React means that once the value of a parent component is set, the children component cannot alter or modify it.

Lastly, the defaultProps property is a static react component property that allows you to set default values for the props argument. They are useful when a component has optional props that may not always be provided when the component is used.

Emmanuel Uchenna

Emmanuel Uchenna

Emmanuel is an experienced and enthusiastic software developer and technical writer with 4+ proven years of professional experience. He focuses on full-stack web development. He is fluent in React, TypeScript, VueJS, and NodeJS and familiar with industry-standard technologies such as version control, headless CMS, and JAMstack. He is passionate about knowledge sharing.