React Dynamic Component


I first saw this pattern being used in the Material UI source code some time ago. It was indeed pretty mind-blowing for the then me šŸ˜†

Recently, I took a step back, revisit and deep dive each section of React's wonderful "Advanced Guides" docs once again. And I came to realize that the cool magic was in fact, part of JSX itself! I highly recommend that you read through this part of the doc - JSX In Depth, if you haven't.

Secret Sauce in JSX

In this section of the doc, it tells us 2 very important points.

Firstly, elements that start with lowercase letter, which implies any native HTML elements, e.g. div, span, h1, h2, etc. inclusive of Web Component, results in being translated to string and passed to React.createElement call.

1// This Dummy component returns a 'div'
2const Dummy = () => <div>Testing</div>
4// It's equivalent to calling React.createElement with 'div' string
5const SomeComponent = () => React.createElement('div', {}, 'Testing')

Secondly, elements that start with Capital Letter, i.e. some other React Components or some JS variables, will result in the JS object itself being passed to the React.createElement call.

1// With a React component instead of raw `div`
2const SomeComponent = () => <Foo>Testing</Foo>
4// It's equivalent to calling React.createElement with Foo function/class
5const SomeComponent = () => React.createElement(Foo, {}, 'Testing')

When an element type starts with a lowercase letter, it refers to a built-in component likeĀ <div>Ā orĀ <span>Ā and results in a stringĀ 'div'Ā orĀ 'span'Ā passed toĀ React.createElement. Types that start with a capital letter likeĀ <Foo />Ā compile toĀ React.createElement(Foo)Ā and correspond to a component defined or imported in your JavaScript file.

Dynamic Component Example

Supposed we want to build some typographic component that renders Headings dynamically, i.e. h1, h2, h3, h4, h5 and h6.

Drawing from the JSX explanation above, here is how we can do it.

1import React, { FunctionComponent, ReactNode } from 'react';
3interface Props {
4  type: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
5  children: ReactNode;
8const Heading: FunctionComponent<Props> = ({
9  type,
10  children,
11}) => {
12  const Component = type;
14  return (
15    <Component>
16      {children}
17    </Component>
18  )

We just have to assign the type (h1, h2, h3...) to a variable that starts with Capital letter (in this case, 'Component'). And bam, you can use that variable just like a Component in the return portion already.

Here is how it works. The 'type' here is an actual string under the hood, i.e. 'h1', 'h2', 'h3', etc. We just assign the 'type' to another placeholder variable called 'Component', which is then used in the JSX itself. The variable name has to start with capital letter, simply because JSX mandates that only native HTML Elements can be named starting with lowercase.

We can also further save ourselves a few lines, if we assign an alias directly at the Props destructuring call.

1const Heading: FunctionComponent<Props> = ({
2  type: Component,
3  children,
4}) => {
5  return (
6    <Component>
7      {children}
8    </Component>
9  )

Might be too cluttered for some people. So, whether to do it or not... It is totally up to personal preference I supposed. Haha.. šŸ˜†


There we go, that's how to we can utilize JSX to spin up dynamic components in React. In fact, this trick works well with other frameworks that use JSX as well, e.g. Stencil. Check out Stencil if you haven't! It's a toolchain to build Web Components using JSX.

Finally, thank you very much to React's team and community for producing such high quality docs. It is very informative and easy to read. I learn and realize something new every once in a while when I visit the docs!

The magic is in fact, no magic. And that's the beauty of it. That's why we love React!

Was indulging in the aroma and beauty of this great cup of coffee at Apartment Coffee. The floral attribute for this one is simply over the top when it was served. So glad to have sipped on this one!

Coffee time at Apartment Coffee, Sg