David Alsh
David Alsh

Reputation: 7609

Create nested JSX elements from multi-level nested array of objects reactjs

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

Answers (3)

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

Maiya
Maiya

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

Shubham Khatri
Shubham Khatri

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>;
}

Working demo

Upvotes: 3

Related Questions