Search code examples
javascriptreactjsjsxreact-functional-component

Render component by function pointer and pass props


I have an array of pointers, componentArray, but I'm struggling to figure out the syntax to both render them in ParentComponent



function Component1() {
    return(
        <h1>Hello from Component 1</h1>
    );
}

function Component2() {
    return(
        <h1>Hello from Component 2</h1>
    );
}

export const componentObject = [{
    name: "Component1",
    pointer: Component1
}, {
    name: "Component2",
    pointer: Component2
}];

function ParentComponent(props) {
    return (
        <div>
            {Object.entries(componentObject).map((ChildComponent) => (
                <span>{ChildComponent[1]() DOESNOTWORKPROP="Test"}</span>
            ))}
        </div>
      );
};

The above will work if you remove DOESNOTWKRPROP="TEST", but will not work when trying to add props to the children.


Solution

  • Here you should not call directly ChildComponent as a function. You should use the "tag syntax", as follows:

    function ParentComponent(props) {
        return (
            <div>
                {componentObject.map(({ pointer: ChildComponent }) => (
                    <ChildComponent DOESWORKPROP="Test" />
                ))}
            </div>
          );
    };
    

    Note that the variable used in the tag should use PascalCase for react to accept it, thus the renaming as ChildComponent after destructuring pointer.

    Here is the related documentation: https://reactjs.org/docs/jsx-in-depth.html#choosing-the-type-at-runtime

    Bonus: you should provide a prop key to element generated with map. Here you can use the name of your components ;)

    <ChildComponent key={ChildComponent.name} DOESWORKPROP="Test" />
    

    Going further, when you call the function directly here:

    <span>{ChildComponent[1]() DOESNOTWORKPROP="Test"}</span>
    

    Your component is executed immediately and returns static JSX, as if your code became:

    <span>{<h1 DOESNOTWORKPROP="Test">Hello from Component 1</h1>}</span>
    

    That why your props don't apply: they are passed to a static JSX element, not to the dynamic rendering process of your component