DEV Community

Andrew Lee
Andrew Lee

Posted on

How to Dynamically Render Components in React

Sometimes we need to dynamically render React components. For example let's say we are building a drag and drop website builder.

Customer A wants their website to consist of Navbar2, Content1, and Footer3.

<div>
  <Navbar2 />
  <Content1 />
  <Footer3 />
</div>
Enter fullscreen mode Exit fullscreen mode

Customer B on the other hand wants a slightly different website.

<div>
  <Navbar1 />
  <Content3 />
  <Footer1 />
</div>
Enter fullscreen mode Exit fullscreen mode

If we have a lot of components, we are going to end up creating a component for every single possible combination...or we can use dynamic rendering.

First, we need a mapping of our components.

// i.e. const Navbar1 = () => <div>Navbar1</div>

const componentMapping = {
  Navbar1,
  Navbar2,
  Navbar3,
  Content1,
  Content2,
  Content3,
  Footer1,
  Footer2,
  Footer3
};
Enter fullscreen mode Exit fullscreen mode

Then we can render the website for Customer A

const customerA = ['Navbar2', 'Content1', 'Footer3'];
Enter fullscreen mode Exit fullscreen mode

and for Customer B

const customerB = ['Navbar1', 'Content3', 'Footer1'];
Enter fullscreen mode Exit fullscreen mode

with the same dynamic component.

// <Website config={customerA} />
// <Website config={customerB} />

const Website = (props) => {
  return (
    <div>
      {config.map((componentName) => {
        const Component = componentMapping[componentName];
        return <Component />;
      })}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Top comments (5)

Collapse
 
devhammed profile image
Hammed Oyedele •

Not so efficient because the components are still rendered but not in the DOM, a better option is to use function that return the component in the mapping then call the function in map callback.

Collapse
 
andyrewlee profile image
Andrew Lee •

Good catch! Just noticed the typo in my componentMapping. Before it was something like

const componentMapping = {
  Navbar1: <Navbar1 />
}

I just changed it to this so we render in the map callback.

const componentMapping = {
  Navbar1
}
Collapse
 
devhammed profile image
Hammed Oyedele •

Oh...I get it now.
😁😁😁

Collapse
 
tsengtofu profile image
Tseng Tofu •

What if the Navbar component or other component need to pass props?Is this still work?

Collapse
 
kyh profile image
Kaiyu Hsu • • Edited

You could update your component list to contain the props:

const customerA = [
    { componentName: 'Navbar2', props: { foo: "bar" } },
    { componentName: 'Content1', props: {} },
    { componentName: 'Footer3', props: {} }
];
Enter fullscreen mode Exit fullscreen mode

and your renderer would look like:

const Website = ({ config }) => {
  return (
    <div>
      {config.map(({ componentName, props }) => {
        const Component = componentMapping[componentName];
        return <Component {...props} />;
      })}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode