Derek 朕會功夫
Derek 朕會功夫

Reputation: 94319

How do I create a component by reference?

Suppose I have:

import MyComponent from "../somewhere"

I can create an instance of it by doing:

<MyComponent myprops={myprops} />

But can I create one programmatically from MyComponent and add props?


For example, I have a list of component references:

import comp1 from "somewhere"
import comp2 from "somewhere"
import comp3 from "somewhere"

var myComponents = [
    comp1, comp2, comp3
];

And now I have to take one of them and put in the view:

var randomComponent = myComponents[Math.random() * 3 | 0];

// render
render(){
    return randomComponent; // this doesn't work and certain props have to be added
}

Is there a way to avoid doing the following and achieve the same?

var myComponents = [
    <comp1 props=... />, <comp2 props=... />, <comp3 props=... />
];

Upvotes: 3

Views: 130

Answers (3)

Lauren
Lauren

Reputation: 2627

Thought I would share. I had a very specific use case for this using imported svg files, but I believe this would work with components as well. I wanted to have a button component that would load different svg icons given a prop type.

import LightBulb from '../my-icons/Lightbulb.svg';

const ICON_TYPES = {
  LightBulb: 'LightBulb',
};

const ICON_TYPE_FILES = {
  [ICON_TYPES.LightBulb]: LightBulb,
};

export default function IconButton({iconType}) {
  const IconComponent = ICON_TYPE_FILES[iconType];
  return (
    <Icon>
      <IconComponent />
    </Icon>
   );
};
IconButton.ICON_TYPES = ICON_TYPES

Using component:

<IconButton
  iconType={IconButton.ICON_TYPES.LightBulb}
/>

Upvotes: 0

Andrew Li
Andrew Li

Reputation: 57964

You can do the following:

var RandomComponent = myComponents[Math.random() * 3 | 0];

render() {
    return <RandomComponent props={foobar} />;
}

The above is demonstrated at the React Docs where the following is mentioned:

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. (emphasis mine)

The reason why the component's name must be capitalized is because it will be treated as a built-in component (DOM component) if not. This works because it's just transpiled into this:

React.createElement(RandomComponent, { props: foobar });

And RandomComponent still refers to a random selected component. If randomComponent is not capitalized, you can just do it without JSX like so:

React.createElement(randomComponent, { props: foobar });

You just won't be able to do it with JSX because randomComponent is lowercase and will incidentally be transpiled into this:

React.createElement("randomComponent", { props: foobar });

Which is problematic as "randomComponent" does not refer to randomComponent.

Upvotes: 4

FuzzyTree
FuzzyTree

Reputation: 32402

see Create react component dynamically

var component = myComponents[Math.random()*3 |0];
return React.createElement(component, props);

Upvotes: 2

Related Questions