eltiare eltiare - 1 month ago 7
Javascript Question

Setting custom props on a dynamically created React component

I'm refactoring some of my React code for ease of use in places where I can't use Babel directly (such as in short embedded JavaScript on pages). To assist with this I'm setting up a short function that builds the components and passes props to them. This code works just fine:

components.js:

import ResponsiveMenu from './components/responsive-menu';
window.setupMenu = (items, ele) => {
ReactDOM.render(<ResponsiveMenu items={items}/>, ele);
};


static-js.html:

<div id="menu"></div>
<script>
setupMenu({ items: [] }, document.getElementById('menu');
</script>


However, when I attempt to turn it into something more generic to handle more components like so:

components.js:

import ResponsiveMenu from './components/responsive-menu';
import AnotherComp from './components/another-comp';

window.setupComponent = (selector, name, props) => {
let eles;

if (typeof selector == 'string') {
eles = [];
let nl = document.querySelectorAll(selector), node;
for (let i = 0; node = nl[i]; i++) { eles.push(node); }
} else {
eles = $.toArray(selector); // A helper function that converts any value to an array.
}

return eles.map (
(ele) => {
let passProps = typeof props == 'function' ? props(ele) : props;
return ReactDOM.render(React.createElement(name, passProps), ele);
}
);
};


static-js.html:

<div id="menu"></div>
<script>
setupComponent('#menu', 'ResponsiveMenu', { items: [] });
</script>


I then get this error:
Warning: Unknown prop "items" on <ResponsiveMenu> tag. Remove this prop from the element. For details, see (really unhelpful shortened link that SO doesn't want me posting)


Please help me understand why this works for the JSX version and not for the more manual version of creating the component.

Answer

When you pass string parameter to React.createElement, it will create native DOM element and there is no valid html DOM ResponsiveMenu.

You can store element into hash and store it into window variable.

Example:

// store component into window variable
window.components = {
     ResponsiveMenu: ResponsiveMenu
}

//extract component from window variable by name
React.createElement(window.components[name], passProps)