How to dynamically render ReactJS components

Published on Sunday, 9 April 2017

How to dynamically render ReactJS components

Recently I needed a way to dynamically render React components based on its name and I didn't find much information. So I decided to create a summary with some examples to illustrate it.

For this example we have a parent component where we want to render a specific child component based on its component name (string):

<Parent>
    <Child1 />
    <Child2 />
    <Child3 />
    <ChildN />
</Parent>

Where Child1, Child2, Child3, ChildN string not variables.

So how we can do it?

We can't pass the string "as is" because it doesn't work:

<Parent> 
    <'Child1' />
    <'Child2' />
    <'Child3' />
    <'ChildN' />
</Parent>

We have bunch of erros.

Lets try to create variables:


class Child1 extends React.Component {
 	render() {
  	return <input type="text" placeholder="Text here" />;
  }
 }
 
 class Child2 extends React.Component {
 	render() {
  	return <button>button here</button>;
  }
 }
 
class App extends React.Component {
 	render() {
    var C1 = this.props.names[0];
    var C2 = this.props.names[1];
  	return <div>
    			<C1 />
	      	    	<C2 />
      		</div>;
  }
 }



 React.render(<App names={['Child1','Child2']} />,document.getElementById('container'));

(example on jsfiddle: https://jsfiddle.net/alexvab/39brybk0/)


This won't work either. As you can see in chrome dev tools this time we don't have errors but instead of rendering components ReactJS just create html tags

<div id="container">
    <div data-reactid=".0">
        <child1 data-reactid=".0.0"></child1>
        <child2 data-reactid=".0.1"></child2>
    </div>
</div>

So what we can do here? The idea is simple. We can create a js object where properties are the same as control names and the property value is the React component variable (class):


var componentList = {
    Child1: ChildComponent1,
    Child2: ChildComponent2
}

And then we could access it this way

var componentName = 'Child1';
var ChildComponent = componentList[componentName];

And then we could render it like usual:

render() {
    return <ChildComponent />
} 

Note:

It is very important to start your variable name with capital letter.

(For example, ChildComponent or Control works but not childComponent or control). Otherwise React wouldn't understand it.

Lets create a more real-world example to illustrate this better.

We have a component called ControlPanel which we want to use as a container for some other html inputs. For example text, button and textarea, etc.

Example:

class TextBox extends React.Component {
 	render() {
  	return <input type="text" placeholder={this.props.text} />;
  }
 }
 
 class Button extends React.Component {
 	render() {
  	return <button>{this.props.text}</button>;
  }
 }
 
 
 class TextArea extends React.Component {
 	render() {
  	return <textarea>{this.props.text}</textarea>;
  }
 }
 
class ControlsPanel extends React.Component {
 	render() {
  	var controlList = {
    	TextBox: TextBox,
      Button: Button,
      TextArea: TextArea,
    }
    
  	var controls = this.props.controlNames.map(function(name, index) {
    	var Control = controlList[name];
      return <Control key={'ctrl-' + index } text={'this is a ' + name} />;
    });
    
  	return  <div>
    		    {controls}
            </div>;
  }
 }
 
 
 React.render(<ControlsPanel controlNames={['TextBox', 'Button', 'TextArea']} />,document.getElementById('container'));

Result:

image

(example on jsfiddle: https://jsfiddle.net/alexvab/rzqfp8fd/)


I hope this helps you, (for more information see this github issue).
Happy coding!