React Dynamic Component

Introduction

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.

// This Dummy component returns a 'div'
const Dummy = () => <div>Testing</div>

// It's equivalent to calling React.createElement with 'div' string
const 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 function itself being passed to React.createElement call.

// With JSX 
const SomeComponent = () => <Foo>Testing</Foo>

// It's equivalent to calling React.createElement with Foo function/class
const 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.

https://reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized

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.

import React, { FunctionComponent, ReactNode } from 'react';

interface Props {
  type: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
  children: ReactNode;
}

const Heading: FunctionComponent<Props> = ({
  type,
  children,
}) => {
  const Component = type;

  return (
    <Component>
      {children}
    </Component>
  )
}

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.

const Heading: FunctionComponent<Props> = ({
  type: Component,
  children,
}) => {
  return (
    <Component>
      {children}
    </Component>
  )
}

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

Conclusion

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

References

  1. https://reactjs.org/docs/jsx-in-depth.html
  2. https://reactjs.org/community/team.html
  3. https://developer.mozilla.org/en-US/docs/Web/HTML/Element
  4. https://developer.mozilla.org/en-US/docs/Web/Web_Components