1

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>
4
  • How many levels of children elements do you have? Commented Sep 13, 2019 at 4:55
  • @ShubhamKhatri theoretically infinite Commented Sep 13, 2019 at 4:56
  • Have you tried anything so far? Commented Sep 13, 2019 at 4:58
  • sadly, nothing valuable Commented Sep 13, 2019 at 5:01

3 Answers 3

3

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

Sign up to request clarification or add additional context in comments.

2 Comments

David, let me know if the above answer helps you or not
If it did not help him, it helped me (as I only knew how to do it w/ JSX).
2

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();

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.