ajthinking
ajthinking

Reputation: 4568

Cannot create react element from string

I have a factory where I want to spawn react components. For now I have Load and Migrate. Passing the imported name directly works fine:

...

return React.createElement(Migrate, {
    node: node,
    diagramEngine: diagramEngine
});

But I would like to insert the name dynamically.

...    

var ElementToCreate = node.state.manipulator.name;

return React.createElement(ElementToCreate, {
    node: node,
    diagramEngine: diagramEngine
});

But this blows up with error message:

Warning: Unknown props node, diagramEngine on tag. Remove these props from the element

Passing raw strings "Migrate" or "Load" also fails. Following the tips here did not help me identify the issue. Any ideas?

Upvotes: 1

Views: 327

Answers (2)

ajthinking
ajthinking

Reputation: 4568

See AKX answer. For sanity as I will have lots of imports, I also moved it all to its own file.

import Load from "./Load";
import Migrate from "./Migrate";
...

const AllManipulators = {
    Load,
    Migrate
    ...
};

export default AllManipulators;

Then

import AllManipulators from "./AllManipulators"
return React.createElement(AllManipulators[name], {
    node: node,
    diagramEngine: diagramEngine
});

Upvotes: 1

AKX
AKX

Reputation: 169032

If you pass in a string as the first argument to React.createElement, it will be considered an HTML tag name, which isn't what you want.

Instead, use a registry to map from name to actual component class:

import Foo from './Foo';
import Bar from './Bar';
import Quux from './Quux';

const TYPE_REGISTRY = {
    // Using ES object literal shorthand to
    // avoid repeating the names
    Bar,
    Foo,
    Quux,
};

// ...

class ... {

    render() {
        // typeName would be one of "Bar", "Foo" or "Quux".
        const typeName = node.state.manipulator.name;
        const element = TYPE_REGISTRY[typeName];
        if(!element) {
            return <div>Invalid type name {typeName}</div>;
        }
        return React.createElement(element, {node, diagramEngine});
    }
}

Upvotes: 1

Related Questions