最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Rendering React components from json data dynamically - Stack Overflow

programmeradmin3浏览0评论

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 ponents 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 ponent, 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 ponent 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);
    }

    ponentWillMount() {}

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

    ponentWillMount() {}

    render() {

        return <h2>In App</h2>;
    }
}

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 ponents 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 ponent, 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 ponent 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);
    }

    ponentWillMount() {}

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

    ponentWillMount() {}

    render() {

        return <h2>In App</h2>;
    }
}
Share Improve this question edited Jan 23, 2018 at 13:41 learner asked Jan 23, 2018 at 13:22 learnerlearner 4,8189 gold badges57 silver badges101 bronze badges 8
  • 2 I suggest you to take a look at this: mozilla-services.github.io/react-jsonschema-form – Black.Jack Commented Jan 23, 2018 at 13:29
  • Thanks. But, that is a huge library. I am looking for answers related to my scenario. – learner 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. – Black.Jack Commented Jan 23, 2018 at 13:36
  • can you post TextField ponent? – Ali Faris Commented Jan 23, 2018 at 13:38
  • @Ali Please have a look. – learner Commented Jan 23, 2018 at 13:41
 |  Show 3 more ments

3 Answers 3

Reset to default 4

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

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>
    }
}
GetFromJson = ({ children }) => {
   return children.map(elem => {
       const Tag = elem.baseType
       const props = { elem }
       return (
          <Tag> ...props </Tag>
       )
   })
}

And then in your ponent

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

Probably you have issue with binding,try this

constructor(props) {
  super(props);

  this.getFromJson = this.getFromJson.bind(this);
}
发布评论

评论列表(0)

  1. 暂无评论