fractal5
fractal5

Reputation: 2132

React - Reference a component using a string

I need to call a component by using a string that is the same as the component name.

Is there a way to do this without using switch or mapping the strings to the components, which I am able to do currently.

I tried this, but it doesn't work, although this article uses a similar approach.

render() {
     let CompName = 'SelectComponent';
     return <CompName />
}

This is just an example. The strings (component names) will be defined in an config file, which holds properties for several input fields that need to be rendered.

Thanks.

Upvotes: 1

Views: 2022

Answers (3)

Estus Flask
Estus Flask

Reputation: 222840

Is there a way to do this without using switch or mapping the strings to the components

There is no way because the framework doesn't have a way to associate component function names with components.

There should be a map that maps components to their names, e.g.:

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

const componentsMap = { Foo, Bar };

...

let CompName = 'Foo';
return <componentsMap[CompName] />

The workflow can be improved with a decorator, especially for class components:

const componentsMap = {};

const mapComponent = name => Comp => {
  name = name || Comp.displayName;
  if (!name)
    throw new Error('no comp name');

  return componentsMap[name] = Comp;
}

...

@mapComponent()
class Foo extends Component {
  static displayName = 'Foo';
  ...
}

const Bar = mapComponent('Bar')(props => ...);

Component name can be moved to static property like displayName but cannot be avoided because function name property is mangled during minification and cannot be relied on.

Upvotes: 0

KornholioBeavis
KornholioBeavis

Reputation: 2442

I think the closest you can get to is calling an object property via string

const Component1 = ()=><h1>This is component 1</h1>
const Component2 = () => <h1>This is component 2</h1>

const obj = {
 component1: <Component1 />,
 component2: <Component2 />
}

render(obj["component2"], document.getElementById("app"));

Upvotes: 0

Tholle
Tholle

Reputation: 112867

You can use strings for built-in elements (div, span, ...) but if you want to use a custom component, you need a reference to the component variable.

You can put all your components in an object and get the component variable with the help of the component name.

Example

function Foo() {
  return <div> Foo </div>;
}
function Bar() {
  return <div> Bar </div>;
}

const components = { Foo, Bar };

function App(props) {
  const { regularTag: RegularTag, componentTag } = props;
  const Component = components[componentTag];

  return (
    <div>
      <Component />
      <RegularTag> Baz </RegularTag>
    </div>
  );
}

ReactDOM.render(
  <App componentTag={"Foo"} regularTag={"div"} />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

Upvotes: 1

Related Questions