19

So, i’d like to spare time later and want to do a dynamically generated page. For that reason i want to read component data from an object, like this:

  layout: {
    toolbar: {
      components: [
        {
          type: "Testcomp",
          theme: "default",
          data: "div1"
        },
        {
          type: "Testcomp",
          theme: "pro",
          data: "div2"
        },
      ]}}

The component would be dynamically imported, enabled/activated and besides that this is the jsx code supposed to render components dynamically:

render() {
    const toolbarComponents = userSession.layout.toolbar.components.map(Component => (
      <Component.type theme={Component.theme} data={Component.data} key={this.getKey()} />
    ));

    return (
      <div>
        <div className="toolbar">
          toolbar
          {toolbarComponents}
        </div>
    . . .
      </div>
    );
  }

However i get the following warning in Chrome’s devtool, also the component is not displayed:

Warning: is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.

Warning: The tag is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.

What’s wrong with my code?

Jacob
  • 77,566
  • 24
  • 149
  • 228
inspiral
  • 611
  • 1
  • 7
  • 15

3 Answers3

14

You are getting those errors because you are not referencing the component itself here, instead using a string as name. So, maybe you need to think another way to create the components dynamically. Like starting with a base component and only give some props and data to it.

// Define above main component or elsewhere then import.
const MyComponent = ( props ) => <div>{props.data}</div>

// Main component
render() {
  const toolbarComponents = userSession.layout.toolbar.components.map(
    component => <MyComponent theme={component.theme} data={component.data} />
  );

  return <div className="App">{toolbarComponents}</div>;
}

Here we are not using a type key anymore. If you want to use different components like that, you can create every base component and then use as its name with type key but not with string, directly referencing the component.

devserkan
  • 16,870
  • 4
  • 31
  • 47
  • 2
    Yes, my problem at the first place was that i was only referencing to a string instead of an object. As for the proposed alternative solution, it is a good idea but for another time. – inspiral May 24 '18 at 10:47
0

I tried using the same method as you, wherein I was using a string to reference a React component by name. However, it doesn't appear designed to be used outside of standard tags like div.

Instead, what worked for me is to import the component I wanted to show and then set that in the state.

import MyComponent from 'mycomponent';

class Parent extends React.Component {
  constructor() {
    super();
    this.state = {
      selectedComponent: null
    };
  }

  render() {
    return (
      <div className="Parent">
        <h2>Parent Component</h2>
        <button onClick={() => this.setState({ selectedComponent: MyComponent })}>Show my component</button>
          {this.state.selectedComponent !== null && React.createElement(this.state.selectedComponent, null, null)}
        </div>
    );
  }
}
cst1992
  • 3,823
  • 1
  • 29
  • 40
0

For me I got this issue once I mistaken in return rather then returning a component I returned a state variable

if (showClients) {
  return <showClients />
}

so I go this warning

Warning: <showClients /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.
showClients

So I had simply to use the correct component

export default function Evaluation() {
  ...
  if (showClients) {
    return <EvaluationClients />;
  }
  return (
    <div>
     ...
    </div>
  );
}
DINA TAKLIT
  • 7,074
  • 10
  • 69
  • 74