TypeOfNaN

How to conditionally wrap JSX with a component in React

Nick Scialli
June 14, 2021

Sometimes we want to have content in React be wrapped in another component, and sometimes we don’t. In this post, we create a Wrapper that either renders its children in a component or it doesn’t.

An example scenario

Let’s say we have some JSX that will either be shown in-app or, in another scenario, will be shown inside a modal. We have a Modal component, but we’re not quite sure How to efficiently render the JSX inside it or not.

An initial approach

One approach could be to repeat the content, once inside the modal and once not inside the modal. Then, we use a ternary operator to show one version or the other:

function MyComponent(props) {
  return (
    <div>
      <h1>Some content here</h1>
      <p>Some other content</p>
      {props.showModal ? (
        <Modal>
          <h2>Flexible content</h2>
          <p>This is some content that may be in a modal or may not.</p>
        </Modal>
      ) : (
        <>
          <h2>Flexible content</h2>
          <p>This is some content that may be in a modal or may not.</p>
        </>
      )}
    </div>
  );
}

Of course, this is pretty ugly! We’re violating the Don’t Repeat Yourself (DRY) tenet of programming. One way we could make this a bit better is to store our repeated content in a variable:

function MyComponent(props) {
  const content = (
    <>
      <h2>Flexible content</h2>
      <p>This is some content that may be in a modal or may not.</p>
    </>
  );

  return (
    <div>
      <h1>Some content here</h1>
      <p>Some other content</p>
      {props.showModal ? <Modal>{content}</Modal> : content}
    </div>
  );
}

This cleans it up quite a bit! But there’s another way that I think can make our code look cleaner and give us a lot more flexibility and reusability—creating a wrapper component that lets us render the content based on its props.

A wrapper component

Let’s create a wrapper component that takes showModal as a prop. If that prop is truthy, we show the component’s children in a modal. If not, we just return the children:

function Wrapper(props) {
  if (props.showModal) {
    return <Modal>{props.children}</Modal>;
  }
  return props.children;
}

Then, we can pull this into our other component like so:

function MyComponent(props) {
  return (
    <div>
      <h1>Some content here</h1>
      <p>Some other content</p>
      <Wrapper showModal={props.showModal}>
        <h2>Flexible content</h2>
        <p>This is some content that may be in a modal or may not.</p>
      </Wrapper>
    </div>
  );
}

I think this looks pretty clean. It gives us more options of what we can render inside the Wrapper (perhaps we have more than two permutations). Also, Wrapper is now reusable in case this is a patter throughout the application.

Nick Scialli

Nick Scialli is a senior UI engineer at Microsoft.

© 2024 Nick Scialli