简体   繁体   中英

React createElement does not add children of type string when mutiple children are part of inner html

I am using React.createElement(...) to dynamically generate a basic react site using a json file.

The json file is array of JSON objects which represent an element (and its children). The JSON object for an individual element looks like this.

{
    "id": "e960f0ad-b2c5-4b0b-9ae0-0f6dd19ca27d",
    "render": true,
    "component": "small",
    "styles":[],
    "classes":[],
    "children": [
        "©2017",
        {
            "id": "04fa3b1a-2fdd-4e55-9492-870d681187a4",
            "render": true,
            "component": "strong",
            "styles":[],
            "classes":[],
            "children": [
                "Awesome Company"
            ]
        },
        ", All Rights Reserved"
    ]
}

this object "should" ideally generate the following html code

<small>©2017 <strong>Awesome Company</strong>, All Rights Reserved</small>

I have created react components to render these html elements for example

Small.jsx

import React from 'react'

const Small = ({ id, className, style, children }) => {
    return (
        <small id={id} style={style} className={className}>
            {children}
        </small>
    )
}

export default Small

Similarly I have created jsx for other html elements like anchor tag, div, footer, button etc

There is renderer.js which is called by App.js to render each component in the json file

import React from 'react'
import Button from "../components/Button";
import Input from "../components/Input";
import Header from "../components/header/Header";
import Footer from "../components/footer/Footer";
import Div from "../components/containers/Div";
import Article from "../components/containers/article/Article";
import Fragment from "../components/containers/Fragment";
import Anchor from "../components/Anchor";
import Nav from "../components/Nav";
import Heading1 from "../components/typography/Heading1";
import Strong from "../components/typography/Strong";
import Small from "../components/typography/Small";

const componentMap = {
    button: Button,
    input: Input,
    header: Header,
    footer: Footer,
    div: Div,
    article: Article,
    fragment: Fragment,
    a: Anchor,
    nav: Nav,
    h1: Heading1,
    small: Small,
    strong: Strong
};

const generateComponentStyles = (styles) => {
    let mappedStyles = {};
    styles.forEach(style => {
        mappedStyles[style.name] = style.value;
    });
    return mappedStyles;
}

function renderer(config) {
    if (typeof componentMap[config.component] !== "undefined") {

        //creating children array for this element
        let elementChildren = [];
        if(config.children && config.children.length > 0) {
            for (let index = 0; index < config.children.length; index++) {
                const child = config.children[index];
                if(typeof config.children === "string") {
                    elementChildren.push(child);
                } else {
                    elementChildren.push(renderer(child));
                }
            }
        }

        return React.createElement(
            componentMap[config.component],
            {
                id: config.id,
                key: config.id,
                className: config.classes ? config.classes : null,
                style: config.styles ? generateComponentStyles(config.styles) : null
            },
            elementChildren
        );
    }
}
  
export default renderer;

The problem is even when the <small> tag is generated with the inner html of <strong> but it skips inserting the pure text within the small and strong tags, so the elements come out as empty.

This is what is generated on the site

<small id="e960f0ad-b2c5-4b0b-9ae0-0f6dd19ca27d" class=""><strong id="04fa3b1a-2fdd-4e55-9492-870d681187a4" class=""></strong></small>

As you can see it did not insert the text.

If I however do not supply an array to the "children" attribute but just give a simple string then it shows up. This same thing happens on an anchor tag.

Based on this link: https://reactjs.org/docs/react-api.html#createelement the createElement takes the third param as array of children.

I even tried to wrap my text in an empty fragment to pass it but it did not work either.

How do I insert a plain text within the inner html of an anchor, small, strong etc when there are other children to be inserted as well?

This might be a simple one, because as far as I understood it mainly works with the exemption of the string nodes.

Please check the condition:

typeof config.children === "string"

should be

typeof child === "string"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM