Dynamic Components in React
Tags: react, javascript
Published: 2019-07-01 11:40:25

When we talk about dynamic components in react, we generally see posts on loading components lazily using react-loadable or importing the components lazily during runtime. But, here I want to share a different use case of dynamic Components which I came across recently in one of my project.

##Long if..else/switch..case block hell

Alright, so I had a use case where the backend was sending me some sort of type and based on that type I had to render that type particular component. Initially it started out with two three components but soon it went till 10 components and more to come. Yes, you can imagine how my code block must be looking, it was something like this:

```javascript

function List(props.type) {
 switch(type) {
  case "type1": {
    return (
      <Type1 />
    )
  }
  case "type2": {
    return (
      <Type2 />
    )
  }
  case "type3": {
    return (
      <Type3 />
    )
  }
  .
  .
  .
  .
  case "type10": {
    return (
      <Type10 />
    )
  }
  default: {
    return (
      <BasicType />
    )
  }
 }
}
```

As we can see this had become too cumbersome to write, update as well as maintain, what I needed was to resolve the component from the type that I was receiving from the backend and return that component but in a much elegant way. 

I started looking at the react docs, that's the first place I go to as the docs are very well written. And, there I found the solution to my problem. It all came down to the basics of React.

According to the docs, 

*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.*

*We recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter, assign it to a capitalized variable before using it in JSX.*

***

Basically, if the element type starts with a lowercase letter then react looks for it inside the default html tags and if the element type starts with an uppercase letter it looks for a custom defined and imported component.

So, all I had to was resolve the component type and assign it to a capitalized variable and return that component. And with the help of docs I was able to achieve this:
***

```javascript

import React from 'react';
import { Type1, Type2, Type3, Type4, Type5,...,Type10, BasicType } from './Types';

const components = {
  basic: BasicType,
  type1: Type1,
  type2: Type2,
  type3: Type3,
  type4: Type4,
  type5: Type5,
  .
  .
  .
  type10: Type10
};

function List(props) {

  // In this line I am resolving the component dynamically at runtime and 
  // assigning it to a capitalized Variable and then I return that 
  // component with whatever extra custom props, methods I want to pass 
  // in it.
  
  const TypeComponent = components[props.type.toLowerCase() || 'basic'];
  return (
   <TypeComponent content={props.content} actions={props.actions} />
  );
}

```

Notice that I pass the **props.type** value to the components object which if the key matches returns the value which is a component and it gets assigned to **TypeComponent**

**[props.type.toLowerCase() || 'basic']** this is nothing but extra safety from my side. I am making sure that the type is in lowercase and if nothing is found or is null then by default resolve it to 'basic'.

And my long **switch/case block hell** was reduced to the above elegant piece of code which is simple to maintain and update.

You can read about this more in the react docs on below links:

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

- https://reactjs.org/docs/jsx-in-depth.html#choosing-the-type-at-runtime


Thanks for taking your time and reading this post! If it was useful to you and if you think it could be useful to others please tweet and share the post.