Skip to content

React Tutorial JSX and Components

Building Reusable React Components

Lesson 26 of 156 2 min read By Deepak Paswan Updated Oct 10, 2026

Runnable lesson · press Try it on the examples to edit and run them here.

The big promise of React is reuse: write a piece of UI once and use it everywhere. This lesson shows how to get there from repeated code.

Step 1: notice repetition

Look at this page. The three buttons are nearly the same.

App.jsx
JSX
function App() {
  return (
    <div style={{ display: "flex", gap: 8 }}>
      <button style={{ padding: "6px 14px", borderRadius: 6, border: "1px solid #333", background: "#fff" }}>Save</button>
      <button style={{ padding: "6px 14px", borderRadius: 6, border: "1px solid #333", background: "#fff" }}>Edit</button>
      <button style={{ padding: "6px 14px", borderRadius: 6, border: "1px solid #333", background: "#fff" }}>Delete</button>
    </div>
  );
}

If the design changes, you must edit three places, and you will forget one.

Step 2: extract a component

Move the repeated markup into a function. What differs (the label) becomes a prop. Props are like function arguments; Understanding Props covers them fully.

App.jsx
JSX
function Button({ label }) {
  return (
    <button style={{ padding: "6px 14px", borderRadius: 6, border: "1px solid #333", background: "#fff" }}>
      {label}
    </button>
  );
}

function App() {
  return (
    <div style={{ display: "flex", gap: 8 }}>
      <Button label="Save" />
      <Button label="Edit" />
      <Button label="Delete" />
    </div>
  );
}

Now a design change happens in one place. The component also gives the markup a name, which makes App read like a description.

What makes a component reusable

1. One clear job. Button renders a button. It does not also fetch data and manage a form. If you cannot describe the component in one short sentence, it may be doing too much.

2. Data comes in through props. Do not hard-code text, URLs or numbers that change from place to place.

3. Behaviour comes in through props too. Let the parent decide what happens on click:

App.jsx
JSX
function Button({ label, onClick }) {
  return <button onClick={onClick}>{label}</button>;
}

function App() {
  const [likes, setLikes] = React.useState(0);
  return (
    <div>
      <Button label="Like" onClick={() => setLikes(likes + 1)} />
      <p>Liked {likes} time{likes === 1 ? "" : "s"}</p>
    </div>
  );
}

The same Button can now save, delete or like, depending on the function it receives.

4. Sensible defaults. A Button that works with only a label is easier to use than one that needs ten props. See Default Prop Values.

5. It does not know where it lives. A reusable component should not rely on being inside a certain page or on global variables.

When not to extract

Do not create a component for a single use of three lines of markup that never changes. Extract when:

  • the markup is repeated,
  • a piece has its own state or logic,
  • or the parent has become hard to read.

Too many tiny components with unclear jobs are as hard to follow as one giant one.

Common mistakes

  • Props for everything. A component with fifteen props is a sign it should be split, or that some props belong together in an object or as children.
  • Copying a component instead of adding a prop for the difference.
  • Defining a component inside another component’s body. The inner one is recreated on every render, which resets its state. Define components at the top level.

Key points

  • Extract repeated markup into a component; turn the differences into props.
  • A reusable component has one job, gets data and behaviour from props and does not depend on its surroundings.
  • Extract when there is repetition, separate state or poor readability, not by reflex.

Exercise: A reusable Badge

Create a Badge component that takes a text and a color prop and shows a small coloured label. Use it three times with different values. —solution

App.jsx
JSX
function Badge({ text, color }) {
  return (
    <span style={{ background: color, color: "#fff", padding: "2px 8px", borderRadius: 999, fontSize: 12 }}>
      {text}
    </span>
  );
}

function App() {
  return (
    <p style={{ display: "flex", gap: 8 }}>
      <Badge text="New" color="#2e7d32" />
      <Badge text="Sale" color="#c62828" />
      <Badge text="Limited" color="#1565c0" />
    </p>
  );
}