Injecting Dynamic Elements to Components

Introduction

Let's say we're working on an UI component library using React JS. We make a super awesome looking button, maybe even the best button in the world. But suddenly, our computer shuts off without saving our component!
Like Tenacious D, we create a tribute to the button which looks like:

Weeks later, another programmer walks over, "Hey, we're converting to using React Router. Can we get a button that can use the Link component?"
Mumbling under your breath, we create yet another Awesome component.

We have ourselves a problem. Everytime there is a new request we have to create new components that are very similar, just using slightly different render elements. What if the company decides to rebrand. Instead of blue, we are a red company now. Little changes to the visuals of these AwesomeButton components need to be updated individually. Think DRY! Is there a better way of doing this? Stay tuned.

Dynamically Injecting Elements

What if the consumer of a component could define its base element? Let's look at the example below:

So we have this new property called tag. Tag will be our way of passing in an element/component into AwesomeButton. If the es6 destructing looks different, let me explain. We will pull out the tag prop from this.props. If no value is defined for tag, we will set its default value to be "button" (A Button HTML element).
The next line, const Tag = tag; is so we can fulfill what React's JSX considers a component. All components must be uppercased, where html elements need to be lowercase. Since we are using then variable tag, JSX will always treat the incoming values as a component. So, we have to uppercase our variable.
We now render the prop Tag as our element. Whatever tag equals, that will be our element!

JSX Transformations

Our JSX, in the render function, gets transformed into plain jsx functions that the browsers can use. With this in mind, our AwesomeButton's JSX gets transformed into a React.createElement() function with the element name as the first argument.
With the help of our good friend Babel, let's see what different components compile to!

First, let's look at a simple component that just renders a div with the text "test".

Woah, our Tag variable just gets put where the element is! This is exactly the same to how components are treated in JSX. They get ploped straight into the first argument of React.createElement. Now, when the boss asks for a new feature in AwesomeButton, we only have to change this one implementation of the component. All consumers of the component might use it vastly differently, but we are able to keep our code DRY and highly reusable!