Skip to content
On this page

React Component Composition

Essentially a React application is a bunch of React components arranged in the shape of a tree. When you learned about initializing components as elements in JSX, you have seen how they are used like any other HTML element in JSX. However, until now we have only used them as self-closing tags. What if there could be an opening and closing tag instead for React elements too? Entering the concept of component composition:

src/App.jsx

jsx
const App = () => {
  ...

  return (
    <div>
      <h1>My Hacker Stories</h1>

      <InputWithLabel
        id="search"
        value={searchTerm}
        onInputChange={handleSearch}
      >
        Search:
      </InputWithLabel>

      ...
    </div>
  );
};

Component composition is one of React's more powerful features. Essentially we'll discover how to use a React element in the same fashion as an HTML element by leveraging its opening and closing tag.

In the previous example, instead of using the label prop from before, we inserted the text "Search:" between the component's element's tags. In the InputWithLabel component, you have access to this information via React's children prop now. Instead of using the label prop, use the children prop to render everything that has been rendered in between the <InputWithLabel> opening and closing tag:

src/App.jsx

jsx
const InputWithLabel = ({
  id,
  value,
  type = 'text',
  onInputChange,
  children,
}) => (
  <>
    <label htmlFor={id}>{children}</label>
    &nbsp;
    <input
      id={id}
      type={type}
      value={value}
      onChange={onInputChange}
    />
  </>
);

Now the React component's elements behave similarly to native HTML. Everything that's passed between a component's elements can be accessed as children in the component and be rendered somewhere. Sometimes when using a React component, you want to have more freedom from the outside regarding what to render on the inside of a component:

src/App.jsx

jsx
const App = () => {
  ...

  return (
    <div>
      <h1>My Hacker Stories</h1>

      <InputWithLabel
        id="search"
        value={searchTerm}
        onInputChange={handleSearch}
      >
        <strong>Search:</strong>
      </InputWithLabel>

      ...
    </div>
  );
};

With the React children prop, we can compose React components into each other. We've used it with a string and with a string wrapped in an HTML <strong> element, but it doesn't end here. You can pass React elements via React children as well -- which you should definitely explore more as an exercise.

Exercises: