1

I basically want to have variable components rendered inside a component I'm making which will vary depending on input provided by a user in the prop, but I want to avoid unnecessary if statements and so on.

Would I be able to do that? For example, if the weather prop is defined by the user as Sun, then <{weather}/> would be the same as <Sun />.

PRR
  • 153
  • 4
  • 13

3 Answers3

3

In React, names starting with a capital letter will compile to the createComponent method. So with that in mind, the correct solution is to assign the name value to a capitalized variable (see below).

const WeatherComponent = props => {
  const ComponentTagName = props.weather;

  return <ComponentTagName />
}

Another technique I like to use is mapping child components in an object. This makes the component easier to configure (and reuse) as only an abbreviated key is required instead of the full component name.

import React from 'react';

import SunComponent from './sun-component';
import RainComponent from './rain-component';


const WeatherComponents = {
     Sun: SunComponent,
     Rain: RainComponent
};

const WeatherComponent = (props) => {
    const TagName = WeatherComponents[props.weather || 'Sun'];
    return <TagName />
}
export default MyComponent;
Ali Torki
  • 1,929
  • 16
  • 26
1

You can't really mix JSX syntax with template literals (although anywhere in JSX you could put {a js expession} you could use a template literal, you can't put an expression where a component name is expected).

But since Sun is just a variable with a value that is a component, if you were to call your prop Weather instead of weather you could: <Weather />

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
0

If weather contains a reference to the Sun function, you can use weather directly (not via a template literal), but in lower case JSX will assume it's an HTML tag, not a component, and put it in quotes in the resulting React.creatElement call; so you have to use an initially-capped variable (Weather instead of weather):

<Weather />

If weather contains the string "Sun", you can't directly use it to create a Sun element; you need a reference to the Sun function, not a string. You need a way to get from the string to the function (an object to look it up on, a Map, etc.).


You can use template literals elsewhere in JSX, within {}, since those contain JavaScript expressions. But not to define the component for a tag.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875