futuraprime
futuraprime

Reputation: 5578

Dynamically choosing tag in React

I have some React components that use SVG, and can be contained within an SVG or not. Consequently, I'd like to have a simple way of letting them render inside svg or g, depending on a param, something like:

export default class SVGComponent extends React.Component{
  get containerElement() {
    return this.props.inSVG ? 'g' : 'svg';
  }
  render() {
    return(<{containerElement}>
      <text>Extendable component</text>
    </{containerElement}>);
  }
}

This doesn't work: you can't use template injection in JSX this way. Is there another way I could approach it? It seems like I might be able to do React.DOM[containerElement], but I gather React does not like mixing React.DOM and JSX, and I don't want to move entirely over to React.DOM syntax just for this one function.

Upvotes: 1

Views: 3363

Answers (3)

Thanasis Ioannidis
Thanasis Ioannidis

Reputation: 3231

Take a look at this answer Dynamic tag name in jsx and React

It seems you can create a variable with the first letter capitalized and use it like a component like this

const CustomTag = `h${this.props.priority}`;
<CustomTag>Hello</CustomTag>

If this.props.priority == 3 this will render <h3>Hello</h3>

Upvotes: 3

Davin Tryon
Davin Tryon

Reputation: 67296

I would probably do something like this:

export default class SVGComponent extends React.Component{
  get containerElement() {
    var content = (<text>Extendable component</text>);
    return this.props.inSVG ? (<g>{content}</g>) : (<svg>{content}</svg>);
  }
  render() {
    return({containerElement()});
  }
}

But, it really depends on how dynamic the <text> is.

If the child elements are very dynamic, you might want to render this.props.children and add then as children of the component.

Upvotes: 0

Anton M.
Anton M.

Reputation: 472

You can do it like this

render(){
   var content = <text>Extendable component</text>;
   if(this.props.inSVG){
       return (
           <g>{content}</g>
       );
   }
   else {
       return (
           <svg>{content}</svgg>
       );
   }
}

Upvotes: 1

Related Questions