2017-01-13 2 views
3

Ich brauche in einem ein Kopfelement anzuzeigen Reagieren render Verfahren, bei dem der Pegel dynamisch im Konstruktor festgelegt ist:Reagieren - dynamisch erstellen Tag aus ES6 Vorlage wörtlicher mit JSX

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>

Diese sollte <h2>Header 1</h2> mit name="Header 1" und depth=2, machen aber ich stattdessen eine Fehlermeldung erhalten:

Uncaught Error: Cannot find module "./HeaderComponent"

Was übersehe ich?

Ich benutze React 15.4.1, babel-preset-es2015 6.9.0, babel-preset-react 6.5.0 und läuft es in Chrome 55.

Antwort

3

Each JSX element is just syntactic sugar for calling React.createElement(component, props, ...children). So, anything you can do with JSX can also be done with just plain JavaScript. - https://facebook.github.io/react/docs/react-without-jsx.html

So können Sie etwas zu tun:

render() { 
    return React.createElement(`h${this._checkedDepth}`, this.props) 
} 
+0

Dank. Ich habe mich nur gefragt, ob ich die JSX-Notation wie gezeigt verwenden könnte, aber anscheinend wird dies nicht von der React/Babel React-Voreinstellung unterstützt. – Marc

+0

@ user3676597 (wenn du es nicht wusstest) babel hat einen online transpiler, der alle Fehler hervorhebt, die ich für solche Sachen wirklich nützlich finde - https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets= es2015% 2Creact% 2Cstage-0% 2Cstage-1 & code = –

+0

Es scheint keine Möglichkeit zu bestehen, dynamische Tags in JSX zu erstellen. React.createElement scheint der einzige Weg für jetzt – Pineda

1

Vielleicht zu spät ein wenig, aber Sie können auch ohne React.createClass mit JSX setzt den Tag-Namen in einer Variablen eine Komponente oder einen Tag dynamisch erstellen und Verwenden Sie diese Variable wie bei jeder anderen Komponente.

In Ihrem Fall innerhalb render, sollten Sie so etwas wie:

const TitleTag = `h{ this._checkedDepth }>`; 

return <TitleTag>{ this.props.name }</TitleTag> 

Hinweis das erste Zeichen dieser Variablen müssen reagieren, um zu lassen, groß geschrieben werden wissen, dass eine Komponente Reagieren ist, sonst einen Tag mit der Genau der gleiche Name (nicht Wert) Ihrer Variablen wird stattdessen eingefügt.

Siehe https://reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized:

When an element type starts with a lowercase letter, it refers to a built-in component like <div> or <span> and results in a string 'div' or 'span' passed to React.createElement . Types that start with a capital letter like <Foo /> compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file.

We recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter, assign it to a capitalized variable before using it in JSX.

Es gibt keine Möglichkeit, dies zu tun, ohne diese Variable zu schaffen, so versucht es on the fly zu tun, wie Sie in Ihrem Code zu tun funktionieren (Compiler Begrenzung) nicht.

Hier ist ein voll funktionsfähiges Beispiel:

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>