admin管理员组

文章数量:1244304

I have three ponents:

const Comp0 = () => <div>1</div>;
const Comp1 = () => <div>2</div>;
const Comp2 = () => <div>3</div>;

I have also a class, with state:

state = { activeComponent: 0 }

This activeComponent can be changed by user to 1, 2 or 0.

In render, I have:

return (
   {React.createElement(`Comp${this.state.activeComponent}`)};
}

It should work... theoretically. However - Im getting a really weird error. Two errors.

  1. Warning: <Comp0 /> is using uppercase HTML. Always use lowercase HTML tags in React.

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

How is that possible that they appear simultaneously?

I have three ponents:

const Comp0 = () => <div>1</div>;
const Comp1 = () => <div>2</div>;
const Comp2 = () => <div>3</div>;

I have also a class, with state:

state = { activeComponent: 0 }

This activeComponent can be changed by user to 1, 2 or 0.

In render, I have:

return (
   {React.createElement(`Comp${this.state.activeComponent}`)};
}

It should work... theoretically. However - Im getting a really weird error. Two errors.

  1. Warning: <Comp0 /> is using uppercase HTML. Always use lowercase HTML tags in React.

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

How is that possible that they appear simultaneously?

Share Improve this question edited Mar 16, 2018 at 17:16 iHowell 2,4472 gold badges27 silver badges54 bronze badges asked Mar 16, 2018 at 17:11 PatrickkxPatrickkx 1,8709 gold badges38 silver badges66 bronze badges 7
  • 1 I'm pretty sure React.createElement(...) creates a DOM element and not a React ponent – DevK Commented Mar 16, 2018 at 17:14
  • @devk, no it creates a React ponent too, reactjs/docs/react-without-jsx.html – Shubham Khatri Commented Mar 16, 2018 at 17:16
  • Why do you do it like this? Why don't you just use an if statement? – Janick Fischer Commented Mar 16, 2018 at 17:16
  • @JanickFischer What if I have 100 ponents? Using if for every case would be an overkill. – Patrickkx Commented Mar 16, 2018 at 17:17
  • If you have 100 ponents, you may as well put them into a state array, as I show below. How else would you keep track of them? – iHowell Commented Mar 16, 2018 at 17:18
 |  Show 2 more ments

3 Answers 3

Reset to default 11

You could simply render the dynamic tag like

const Tag = `Comp${this.state.activeComponent}`;
return (
   <Tag />
}

According to the docs:

You cannot use a general expression as the React element type. If you do want to use a general expression to indicate the type of the element, just assign it to a capitalized variable first.

In your case it doesn't work because, you are passing the string name to React.createElement whereas for a React Component you need to pass the ponent like

React.createElement(Comp0);

and for a normal DOM element you would pass a string like

React.createElement('div');

and since you write

`Comp${this.state.activeComponent}`

what you get is

React.createElement('Comp0')

which isn't quite understandable to react and it throws a warning

Warning: <Comp0 /> is using uppercase HTML. Always use lowercase HTML tags in React.

If you were to create a custom ponent element with React.createElement, you have to pass the direct class/function, instead of its name (that's only for DOM elements), to it, e.g. React.createElement(Shoot0) instead of React.createElement('Shoot0');

You can circumvent the issue by putting the ponents you intend for in array and index them

const Shoot0 = () => <div>1</div>;
const Shoot1 = () => <div>2</div>;
const Shoot2 = () => <div>3</div>;

const Shoots = [Shoot0, Shoot1, Shoot2];

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      activeComponent: 0
    };
  }
  
  ponentDidMount() {
    setInterval(() => {
      this.setState((prevState) => {
        return {
          activeComponent: (prevState.activeComponent + 1) % 3
        }
      })
    }, 1000)
  }
  
  render() {
    return React.createElement(Shoots[this.state.activeComponent])
  }
}

ReactDOM.render(<App />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

You can just do a function with a mapping like this:

const stateArray = [Comp0, Comp1, Comp2];
const getComp = (Comp) => <Comp>
const getCompFromArray = (i) => getComp(stateArray[i]);

本文标签: javascriptDynamic component nameReactStack Overflow