Necesito mostrar un elemento de encabezado en un método de render React donde el nivel se establece dinámicamente en el constructor:
class HeaderComponent extends React.Component { constructor(props){ super(props); this._checkedDepth = Math.min(6, props.depth) } render(){ return(<h{ this._checkedDepth }>{ this.props.name }</h{ this._checkedDepth }>) } } ReactDOM.render( <HeaderComponent name="Header 1" depth="2"/>, document.getElementById('app') ); <div id="app"></div> <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> Esto debería mostrar <h2>Header 1</h2> con name="Header 1" y depth=2 , pero aparece un error en su lugar:
Error no detectado: no se puede encontrar el módulo "./HeaderComponent"
¿Qué estoy pasando por alto?
Estoy usando React 15.4.1 , babel-preset-es2015 6.9.0 , babel-preset-react 6.5.0 y ejecutándolo en Chrome 55 .
Cada elemento JSX es simplemente azúcar sintáctico para llamar a React.createElement(component, props, ...children). Por lo tanto, cualquier cosa que pueda hacer con JSX también se puede hacer simplemente con JavaScript. - https://facebook.github.io/react/docs/react-sin-jsx.html
Así que puedes hacer algo como esto:
render() { return React.createElement(`h${this._checkedDepth}`, this.props) }Tal vez un poco tarde, pero puede crear un componente o etiqueta dinámicamente sin usar React.createClass con JSX colocando el nombre de la etiqueta en una variable y usando esa variable como lo haría con cualquier otro componente.
En tu caso, dentro de render , deberías tener algo como:
const TitleTag = `h{ this._checkedDepth }>`; return <TitleTag>{ this.props.name }</TitleTag>Tenga en cuenta que el primer carácter de esa variable debe estar en mayúsculas para que React sepa que es un componente de React; de lo contrario, se insertará una etiqueta con exactamente el mismo nombre (no el valor) de su variable.
Consulte https://reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized :
Cuando un tipo de elemento comienza con una letra minúscula, se refiere a un componente integrado como
<div>o<span>y da como resultado una cadena'div'o'span'pasada aReact.createElement. Los tipos que comienzan con una letra mayúscula como<Foo />se compilan enReact.createElement(Foo)y corresponden a un componente definido o importado en su archivo JavaScript.Recomendamos nombrar los componentes con una letra mayúscula. Si tiene un componente que comienza con una letra minúscula, asígnelo a una variable en mayúscula antes de usarlo en JSX.
No hay forma de hacer esto sin crear esa variable, por lo que intentar hacerlo sobre la marcha como lo hace en su código no funcionará (limitación del compilador).
Aquí hay un ejemplo completamente funcional:
class HeaderComponent extends React.Component { constructor(props) { super(props); const depth = Math.max(Math.min(parseInt(props.depth) || 1, 6), 1); this.state = { depth }; } onClick() { let depth; do { depth = Math.floor(Math.random() * 6) + 1; } while(depth === this.state.depth); this.setState({ depth }); } render() { const Title = `h${ this.state.depth }`; return <Title className="title" onClick={ () => this.onClick() }>{ this.props.name }</Title>; } } ReactDOM.render( <HeaderComponent name="Click Me!" depth="1"/>, document.getElementById('app') ); body { margin: 0; } h1 { font-size: 4rem; } h2 { font-size: 3.5rem; } h3 { font-size: 3rem; } h4 { font-size: 2.5rem; } h5 { font-size: 2rem; } h6 { font-size: 1.5rem; } .title { margin: 0; padding: 0 .5rem; cursor: pointer; user-select: none; } .title:hover { background: #FFA; } <div id="app"></div> <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>