Rendering a component dynamically based on a JSON configuration is a widely used technique in web development. It offers several advantages, such as enhancing a component’s reusability and simplifying updates. To understand this concept further, let’s use a sample JSON configuration data as an example and demonstrate how to dynamically render a component in React code.
Let's take the following JSON config data as an example. We'll use this data in a code example to understand the dynamic rendering of React components.
[{ component: "text", content: "Hey fellas! Meet my pet cat Ziry!" },{ component: "image", src: "/cocomo.jpeg", alt: "My pet cat Ziry" },{ component: "button", label: "Done", action: "Done!" }];
The file hierarchy of the code example is given below:
Import the JSON config data in the main file App.js. If JSON config data is large, we can also create a separate config.json file and import it into our code using import jsonConfig from './config.json';
. However, in this example, we import the entire data in a constant array jsonConfig
.
const jsonConfig = [{ component: "text", content: "Hey fellas! Meet my pet cat Ziry!" },{ component: "image", src: "/cocomo.jpeg", alt: "My pet cat Ziry" },{ component: "button", label: "Done", action: "Done!" }];
Create a separate React component for each element (image, text, button) in JSON config. To do so, first create a components
folder in the src
folder of the React application.
Create a TextComponent.js file in src/components
. The component textComponent
receives its content from JSON config as props
. The content is rendered as an <h2>
</h2>
HTML element using props
, config
referring to the component of type text
in JSON config and content
, i.e., the property of component of type text
in JSON config.
const textComponent = (props) => (<h2 className="text">{props.config.content}</h2>);export default textComponent;
Create a new component file ImageComponent.js in src/components
for the image element in JSON config data. The component imageComponent
receives props
from its parent. The props
are used to render the <img/>
HTML element using src
and alt
, i.e., the properties of the image
element on JSON config.
const imageComponent = (props) => (<img className="image" src={props.config.src} alt={props.config.alt} ></img>);export default imageComponent;
For the button component, create a new file ButtonComponent.js in src/components
. The component receives label
and action
as props
. The onClick()
event uses action
props, and the label of the button is provided by using label
props.
const buttonComponents = (props) => (<button className="button" onClick={()=> alert(props.config.action)}> {props.config.label}</button>);export default buttonComponents;
Now create a separate function to render all the components dynamically. For this, create a new file RenderFunction.jsx in the src
folder. Import all the components in this file.
import TextComponent from "./components/TextComponent";import ImageComponent from "./components/ImageComponent";import ButtonComponent from "./components/ButtonComponent";
Render all these components based on their component key component
in JSON config. For this, first create an object Components
that will map all the components with component keys.
const Components = {text: TextComponent,button: ButtonComponent,image: ImageComponent};
After this, create a function renderComponents
responsible for rendering components. It'll first check if the key exists in the object. If it does, we'll use the React.createElement()
function from the React library to create an instance of the component. Refer here to learn more about createElement()
.
Another argument config
will be passed to React.createElement()
as prop. This means that the config
object will be available as props.config
within the rendered component. This is a way to pass configuration data to the dynamically created component.
However, if the key doesn't exist in the object, the function renderComponents
will return a message saying the component doesn’t exist.
const renderComponents = (config) => {if (typeof Components[config.component] !== "undefined") {return React.createElement(Components[config.component], {config: config});}return React.createElement(() => (<div>Can not find {config.component} component</div>));};
Now, create a map()
function in App.js that parses each element of JSON config and passes it as an argument to the renderComponents()
function.
import Renderer from "./RenderFunction";export default function App() {const renderedComponents = jsonConfig.map((config) => Renderer(config));return <div>{renderedComponents} </div>;}
The entire output of the rendered components will be stored in renderedComponents
.
Here's a complete visual representation of the code example we've discussed above:
Here's the complete executable code:
import React from "react"; const buttonComponents = (props) => ( <button className="button" onClick={()=>alert(props.config.action)}>{props.config.label}</button> ); export default buttonComponents;