8

I have a json object like:

let data = {
            UI: {
                "baseType":"App",
                "children":[
                    {
                        "baseType":"TextField",
                        "props":{

                        }
                    }
                ]
            }
        };

I want to render it like:

<App>
 <TextField>
 </TextField>

So, I need to get dynamically rendered components from json object. For the same, I wrote a method:

getFromJson(obj) {
    // let Type = obj.baseType;

    let children = obj.children
        ? obj.children.map((obj) => {
                return this.getFromJson(obj,obj.baseType);
            })
        : '';
    // <></
    switch (obj.baseType) {
        case "App":

            return (
                <App key={key} {...obj.props}>
                    {children}
                </App>
            );
        case "TextField":
            //      {children}
            //  </TextField>);
            return (<TextField key={key} {...obj.props}>
                    {children}
                </TextField>
            );
        default:
            return <h1>Returning default case.</h1>;
    }

    // return <div>Hello</div>
}

I am calling the above method:

render() {

        let renderedUI = "";
        if (this.props.json.UI) {
            renderedUI = this.getFromJson(this.props.json.UI, "UI");
        }

        return renderedUI;
    }

The output is only App component, i.e., children are not getting rendered. The children although has value: {$$typeof: Symbol(react.element), key: "TextField", ref: null, props: {…}, type: ƒ, …}.

What am I doing wrong?

Edit: My whole component is:

import React from "react";
import TextField from "./TextField";
import App from "./App";

export default class RenderFromJson extends React.Component {
    constructor() {
        super();
        this.getFromJson = this.getFromJson.bind(this);
    }

    componentWillMount() {}

    getFromJson(obj,key) {
        // let Type = obj.baseType;

        let children = obj.children
            ? obj.children.map((obj) => {
                    return this.getFromJson(obj,obj.baseType);
                })
            : '';
        // <></
        switch (obj.baseType) {
            case "App":

                return (
                    <App key={key} {...obj.props}>
                        {children}
                    </App>
                );
            case "TextField":
                //      {children}
                //  </TextField>);
                return (<TextField key={key} {...obj.props}>
                        {children}
                    </TextField>
                );
            default:
                return <h1>Returning default case.</h1>;
        }

        // return <div>Hello</div>
    }

    render() {

        let renderedUI = "";
        if (this.props.json.UI) {
            renderedUI = this.getFromJson(this.props.json.UI, "UI");
        }

        return renderedUI;
    }
}

TextField:

import React from "react";

export default class TextField extends React.Component {
    constructor() {
        super();
    }


    render() {
        console.log("returning from textfield");
        return <h1>Hi from textfield</h1>;
    }
}

App.js

import React from "react";
import axios from "axios";

import RenderFromJson from "./RenderFromJson";

export default class App extends React.Component {
    constructor() {
        super();
    }

    componentWillMount() {}

    render() {

        return <h2>In App</h2>;
    }
}
8
  • 2
    I suggest you to take a look at this: mozilla-services.github.io/react-jsonschema-form Commented Jan 23, 2018 at 13:29
  • Thanks. But, that is a huge library. I am looking for answers related to my scenario. Commented Jan 23, 2018 at 13:34
  • It's not that big. Consider effort to learn a well tested implementation with lots of example other than try to re-invent the wheel. Commented Jan 23, 2018 at 13:36
  • can you post TextField component? Commented Jan 23, 2018 at 13:38
  • @Ali Please have a look. Commented Jan 23, 2018 at 13:41

3 Answers 3

4

finally after one hour I find the issue , your App component will get children array in props object and you must append the children inside your App component

export default class App extends React.Component {
    constructor() {
        super();
    }

    render() {
        return <div>
            <h1>In App</h1>
            {this.props.children /* this what solve the issue */} 
        </div>
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1
GetFromJson = ({ children }) => {
   return children.map(elem => {
       const Tag = elem.baseType
       const props = { elem }
       return (
          <Tag> ...props </Tag>
       )
   })
}

And then in your component

render(){
   return <GetFromJson children={this.props.json.UI.children} />
}

I am just wondering, what do you have in props ? because maybe we need to change the ...props

4 Comments

I can have nested children too. Your case handles only on level of children.
just make a condition that will return another map of your data if you have nested children, for example you check if you have the key children in props and if you do instead of return ...props in you <Tag> you return a map of props.children
This is what I have done in my original code, I think.
you only do a loop on the first children like i did, for now for testing purpose instead of returning <Tag> ...props </Tag>, do <Tag> !props.children ? ...props : null </Tag>
0

Probably you have issue with binding,try this

constructor(props) {
  super(props);

  this.getFromJson = this.getFromJson.bind(this);
}

1 Comment

Nope, same result.

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.