Reputation: 7609
I have the following JSON structure and I need to convert it to an equivalent JSX element structure. The tags can be arbitrary and it can be infinitely nested.
[
{
"tag": "div",
"children": [
{
"tag": "p",
"text": "hey",
"style": {
"color": "red",
"fontSize": "12px"
}
}
]
},
{
"tag": "div",
"text": "Yo"
}
]
Should be rendered as
<div>
<p
style={{
color: 'red',
fontSize: '12px'
}}>hey</p>
</div>
<div>Yo</div>
Upvotes: 1
Views: 2100
Reputation: 1
Adding on to Khatri's example, above, you can return an array within a ternary. My need required showing nested ul > li's and that addition fit my problem.
function renderData(data) {
return data.map(item => {
return React.createElement(
item.tag,
{ style: item.style },
item.children ? [item.text, renderData(item.children)] : item.text
);
});
}
function App() {
return <div className="App">{renderData(data)}</div>;
}
Upvotes: 0
Reputation: 980
Here's a JSX version.
Notice that the recursive call is only called if there are children.
const data = [
{
"tag": "div",
"children": [
{
"tag": "p",
"text": "hey",
"style": {
"color": "red",
"fontSize": "12px"
}
}
]
},
{
"tag": "div",
"text": "Yo"
}
];
const Elements = ({elements}) => {
return (
<React.Fragment>
{elements && elements.map(element => {
let {tag, text, children, style} = element
if(tag === "div") {
return(
<div style={style ? style: {}}>{text}
{children && <Elements elements={children}/>}
</div>
)
} else if(tag === "p") {
return(
<p style={style ? style: {}}>{text}
{children && <Elements elements={children}/>}
</p>
)
}
})}
</React.Fragment>
);}
function render() {
ReactDOM.render(<Elements elements={data} />, document.getElementById("root"));
}
render();
Upvotes: 1
Reputation: 281656
You can recursively call a function and return the rendered element using React.createElement
function renderData(data) {
return data.map(item => {
return React.createElement(
item.tag,
{ style: item.style },
item.children ? renderData(item.children) : item.text
);
});
}
function App() {
return <div className="App">{renderData(data)}</div>;
}
Upvotes: 3