Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering custom html tag with react.js

What I'm trying to do is quite easy at first however I get an (obviously completely useless) error from webpack and I'm wondering how it can be fixed, I want a simple "custom" tag to be rendered by React, the code is as follows:

          let htmlTag = "h" + ele.title.importance;
          let htmlTagEnd = "/h" + ele.title.importance;
          return(
            <{htmlTag} key={elementNumber}>{ele.title.content}<{htmlTagEnd}>
          );

Basically instead of having a predefined tag I want to have my own {template} tag, I know in this situation there would be work arounds for this (e.g. defining a className with my "importance" value and adding some css for that), but for the sake of science I'd like to know how (and if) this can be done in react/jsx.

like image 790
George Avatar asked Dec 04 '16 15:12

George


2 Answers

JSX doesn't allow you to use dynamic HTML tags (dynamic components would work). That's because whenever you use something like <sometag ... />, an HTML element with tag name sometag is created. sometag is not resolved as a variable.

You also can't do what you have shown above. JSX expressions are not valid in place of a tag name.

Instead, you have to call React.createElement directly:

return React.createElement(
  "h" + ele.title.importance,
  {
    key: elementNumber,
  },
  ele.title.content
);
like image 144
Felix Kling Avatar answered Oct 14 '22 07:10

Felix Kling


Edit

My initial answer was not correct, you cannot use a variable directly and would need to use the createElement method described in Felix's answer. As noted below, and utilised in the blog post I originally linked, you can use object properties, so I've made an example of this, which hopefully will be useful as an answer to the question.

class Hello extends React.Component {
    constructor() {
    super();
    this.state = {
        tagName: "h1"
    };
  }

  sizeChange(i) {
    this.setState({
        tagName: 'h' + i
    });
  }

  changeButtons() {
    var buttons = [];
    for (let i=1; i<=6; i++) {
        buttons.push(<button onClick={() => this.sizeChange(i)}>H{i}</button>);
    }
    return buttons;
  }

  render() {
    return (
    <div>
      {this.changeButtons()}
        <this.state.tagName>
        Change Me
      </this.state.tagName>
    </div>
    );
  }
}

JSFiddle here

Original Answer

It can be done, although I don't think it is officially supported so may break in the future without warning. The caveat to this approach is that the variable name you choose for your tag cannot be the same as an HTML element.

var Demo = React.createClass({
    render: function() {
       const elementTag = 'h' + ele.title.importance;
       return(
           <elementTag>
              Header x contents
           </elementTag>
       );
    }
});

More explanation and a fuller example can be found here

like image 45
Alex Young Avatar answered Oct 14 '22 08:10

Alex Young