createElement function of vue js doesn't return compeletly component

Viewed 294

There is a situation which is I need to write a functional component for a specific cause. That is gets all of its children and adds some props to them. But the point is, I need to add those props to just a specific custom components which are of type ChildComponent. I went this way:


MyHigherOrderComponent.vue

    render: function(createElement, context){
        const preparedChildrenLevel1 = context.children.map(child => {
            if(child.componentOptions.tag !== "ChildComponent"){
                return child;
            }

            return createElement(
                ChildComponent,
                {
                    props: {
                        ...child.componentOptions.propsData,
                        level1: "level1"
                    }
                },
                child.componentOptions.children
            )
        });
    },

This actually works fine. Then I want to use preparedChildrenLevel1 to map throw it and add another prop to the children which are of type ChildComponent. But this time I get undefined from child.componentOptions.tag.


MyHigherOrderComponent.vue

    render: function(createElement, context){
        //First level of adding props to children
        const preparedChildrenLevel1 = context.children.map(child => {

            //In here child.componentOptions.tag is equal to 'ChildComponent'
            if(child.componentOptions.tag !== "ChildComponent"){
                return child;
            }

            return createElement(
                ChildComponent,
                {
                    props: {
                        ...child.componentOptions.propsData,
                        level1: "level1"
                    }
                },
                child.componentOptions.children
            )
        });

        //Socond level of adding props to children
        const preparedChildrenLevel2 = preparedChildrenLevel1.map(child => {

            //In here child.componentOptions.tag is equal to 'undefined'
            if(child.componentOptions.tag !== "ChildComponent"){
                return child;
            }

            return createElement(
                ChildComponent,
                {
                    props: {
                        ...child.componentOptions.propsData,
                        level2: "level2"
                    }
                },
                child.componentOptions.children
            )
        });
    },

I need to get this specific type of components in many levels.


Note: Here is my complete implementation of component and how I use it

MyHigherOrderComponent.vue

<script>
export default {
    name: "MyHigherOrderComponent",

    functional: true,

    render: function(createElement, context){
        //First level of adding props to children
        const preparedChildrenLevel1 = context.children.map(child => {

            //In here child.componentOptions.tag is equal to 'ChildComponent'
            if(child.componentOptions.tag !== "ChildComponent"){
                return child;
            }

            return createElement(
                ChildComponent,
                {
                    props: {
                        ...child.componentOptions.propsData,
                        level1: "level1"
                    }
                },
                child.componentOptions.children
            )
        });

        //Socond level of adding props to children
        const preparedChildrenLevel2 = preparedChildrenLevel1.map(child => {

            //In here child.componentOptions.tag is equal to 'undefined'
            if(child.componentOptions.tag !== "ChildComponent"){
                return child;
            }

            return createElement(
                ChildComponent,
                {
                    props: {
                        ...child.componentOptions.propsData,
                        level2: "level2"
                    }
                },
                child.componentOptions.children
            )
        });
    },
}

</script>




App.vue

<template>
    <MyHigherOrderComponent>
        <p>child1</p>
        <p>child2</p>
        <ChildComponent :level0="level0">child3</ChildComponent>
        <p>child4</p>
        <ChildComponent :level0="level0">child5</ChildComponent>
        <ChildComponent :level0="level0">child6</ChildComponent>
    </MyHigherOrderComponent>
</template>

1 Answers

When the element is not a ChildComponent there is no child.components in it so you should add another check in the conditions:

if(!child.componentOptions || child.componentOptions.tag !== "ChildComponent") {
    return child;
}

This way it will ensure that only a ChildComponent is allowed into the rest of your code.
And by the way you're not returning anything in MyHigherOrderComponent's render function

Related