Comment avoir des éléments conditionnels et garder au sec avec Facebook React JSX?

Comment puis-je inclure un élément dans JSX? Voici un exemple en utilisant une bannière qui devrait être dans le composant s'il a été passé. Ce que je veux éviter est d'avoir à dupliquer des balises HTML dans la déclaration if.

render: function () {
    var banner;
    if (this.state.banner) {
        banner = <div id="banner">{this.state.banner}</div>;
    } else {
        banner = ?????
    }
    return (
        <div id="page">
            {banner}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}
222
demandé sur Bergi 2014-03-20 20:03:33

27 réponses

il suffit de laisser banner comme étant non défini et il n'est pas inclus.

146
répondu Jack Allan 2015-04-15 20:15:20

ce. Définissons un simple composant d'aide If .

var If = React.createClass({
    render: function() {
        if (this.props.test) {
            return this.props.children;
        }
        else {
            return false;
        }
    }
});

et l'utiliser de cette façon:

render: function () {
    return (
        <div id="page">
            <If test={this.state.banner}>
                <div id="banner">{this.state.banner}</div>
            </If>
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

mise à jour: comme ma réponse devient populaire, je me sens obligé de vous mettre en garde sur le plus grand danger lié à cette solution. Comme indiqué dans une autre réponse, le code à l'intérieur du composant <If /> est exécuté toujours que la condition soit vraie ou fausse. Par conséquent, l'exemple suivant échouera si le banner est null (notez l'accès à la propriété sur la deuxième ligne):

<If test={this.state.banner}>
    <div id="banner">{this.state.banner.url}</div>
</If>

Vous devez être prudent lorsque vous l'utilisez. Je suggère de lire d'autres réponses pour des approches alternatives (plus sûres).

UPDATE 2: avec le recul, cette approche est non seulement dangereuse mais aussi désespérément lourde. C'est un exemple typique de quand un developer (me) essaie de transférer des modèles et des approches qu'il connaît d'un domaine à l'autre, mais cela ne fonctionne pas vraiment (dans ce cas, d'autres langages de template).

si vous avez besoin d'un élément conditionnel, faites-le comme ceci:

render: function () {
    return (
        <div id="page">
            {this.state.banner &&
                <div id="banner">{this.state.banner}</div>}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

si vous avez également besoin de la branche else, il vous suffit d'utiliser un opérateur ternaire:

{this.state.banner ?
   <div id="banner">{this.state.banner}</div> :
   <div>There is no banner!</div>
}

c'est beaucoup plus court, plus élégant et sûr. Je l'utilise tout le temps. Le seul inconvénient est que vous ne pouvez pas do else if brancher que facilement, mais ce n'est généralement pas si commun.

de toute façon, c'est possible grâce à la façon dont opérateurs logiques en JavaScript fonctionne. Les opérateurs logiques permettent même de petites astuces comme celle-ci:

<h3>{this.state.banner.title || 'Default banner title'}</h3>
129
répondu tobik 2016-10-04 19:49:06

personnellement, je pense vraiment que les expressions ternaires montrent dans http://facebook.github.io/react/tips/if-else-in-JSX.html sont la manière la plus naturelle qui soit conforme aux normes ReactJs.

Voir l'exemple suivant. C'est un peu bordélique à première vue, mais ça marche plutôt bien.

<div id="page">
  {this.state.banner ? (
    <div id="banner">
     <div class="another-div">
       {this.state.banner}
     </div>
    </div>
  ) : 
  null} 
  <div id="other-content">
    blah blah blah...
  </div>
</div>
80
répondu Chiedo 2015-11-05 20:52:07

, Vous pouvez aussi l'écrire comme

{ this.state.banner && <div>{...}</div> }

si votre state.banner est null ou undefined , le côté droit de la condition est sauté.

44
répondu wialy 2018-03-25 22:22:16

le composant de style If est dangereux parce que le bloc de code est toujours exécuté quelle que soit la condition. Par exemple, cela causerait une exception nulle si banner est null :

//dangerous
render: function () {
  return (
    <div id="page">
      <If test={this.state.banner}>
        <img src={this.state.banner.src} />
      </If>
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

une autre option consiste à utiliser une fonction en ligne (particulièrement utile avec les instructions else):

render: function () {
  return (
    <div id="page">
      {function(){
        if (this.state.banner) {
          return <div id="banner">{this.state.banner}</div>
        }
      }.call(this)}
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

une Autre option de réagir questions :

render: function () {
  return (
    <div id="page">
      { this.state.banner &&
        <div id="banner">{this.state.banner}</div>
      }
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}
40
répondu bendytree 2015-02-24 22:16:01

&& + code de style + petits composants

cette syntaxe de test simple + convention de style code + petits composants focalisés est pour moi l'option la plus lisible là-bas. Vous avez juste besoin de prendre un soin particulier des valeurs falsy comme false , 0 ou "" .

render: function() {
    var person= ...; 
    var counter= ...; 
    return (
       <div className="component">
          {person && (
            <Person person={person}/>
          )}
          {(typeof counter !== 'undefined') && (
            <Counter value={counter}/>
          )}
       </div>
    );
}

faire de la notation

ES7 stage-0 do la syntaxe de notation est également très agréable et je vais l'utiliser définitivement quand mon IDE le supporte correctement:

const Users = ({users}) => (
  <div>
    {users.map(user =>
      <User key={user.id} user={user}/>
    )}
  </div>
)  

const UserList = ({users}) => do {
  if (!users) <div>Loading</div>
  else if (!users.length) <div>Empty</div>
  else <Users users={users}/>
}

Plus de détails ici: ReactJs - la Création d'un "Si"... une bonne idée?

22
répondu Sebastien Lorber 2017-05-23 12:26:10

Simple, créer une fonction.

renderBanner: function() {
  if (!this.state.banner) return;
  return (
    <div id="banner">{this.state.banner}</div>
  );
},

render: function () {
  return (
    <div id="page">
      {this.renderBanner()}
      <div id="other-content">
        blah blah blah...
      </div>
    </div>
  );
}

C'est un modèle que je suis personnellement tout le temps. Rend le code vraiment propre et facile à comprendre. De plus, il vous permet de reformuler Banner en son propre composant si il devient trop grand (ou réutilisé ailleurs).

20
répondu Michael Yagudaev 2017-11-27 11:05:34

la syntaxe expérimentale ES7 do rend cela facile. Si vous utilisez Babel, activez la fonctionnalité es7.doExpressions puis:

render() {
  return (
    <div id="banner">
      {do {
        if (this.state.banner) {
          this.state.banner;
        } else {
          "Something else";
        }
      }}
    </div>
  );
}

voir http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions

13
répondu balexand 2015-07-11 02:57:23

comme déjà mentionné dans les réponses, JSX vous présente deux options

  • opérateur ternaire

    { this.state.price ? <div>{this.state.price}</div> : null }

  • conjonction logique

    { this.state.price && <div>{this.state.price}</div> }


cependant, ceux-ci ne travaillent pas pour price == 0 .

JSX rendra la branche fausse dans le premier cas et en cas de conjonction logique, rien ne sera rendu. Si la propriété peut être 0, Il suffit d'utiliser si des déclarations en dehors de votre JSX.

11
répondu Lyubomir 2016-09-12 15:08:45

ce composant fonctionne lorsque vous avez plus d'un élément à l'intérieur de " If "branch:

    var Display = React.createClass({
        render: function() {
            if (!this.props.when) {
                return false;
            }
            return React.DOM.div(null, this.props.children);
        }
    });

Utilisation:

      render: function() {
            return (
                <div>
                    <Display when={this.state.loading}>
                        Loading something...
                        <div>Elem1</div>
                        <div>Elem2</div>
                    </Display>
                    <Display when={!this.state.loading}>
                        Loaded
                        <div>Elem3</div>
                        <div>Elem4</div>
                    </Display>
                </div>
            );
        },

P. S. quelqu'un pense que ces composants ne sont pas bons pour la lecture de code. Mais dans mon esprit html avec javascript est pire

8
répondu k.makarov 2015-01-16 14:29:59

la plupart des exemples sont avec une ligne de" html " qui est rendue conditionnellement. Cela me semble lisible quand j'ai plusieurs lignes qui doivent être rendues conditionnellement.

render: function() {
  // This will be renered only if showContent prop is true
  var content = 
    <div>
      <p>something here</p>
      <p>more here</p>
      <p>and more here</p>
    </div>;

  return (
    <div>
      <h1>Some title</h1>

      {this.props.showContent ? content : null}
    </div>
  );
}

le premier exemple est bon car au lieu de null nous pouvons conditionnellement rendre d'autres contenus comme {this.props.showContent ? content : otherContent}

mais si vous avez juste besoin de montrer / cacher le contenu c'est encore mieux depuis booléens, Null, et non défini sont ignorés

render: function() {
  return (
    <div>
      <h1>Some title</h1>

      // This will be renered only if showContent prop is true
      {this.props.showContent &&
        <div>
          <p>something here</p>
          <p>more here</p>
          <p>and more here</p>
        </div>
      }
    </div>
  );
}
3
répondu ivn 2017-01-02 13:01:34

il existe une autre solution, si composant pour React :

var Node = require('react-if-comp');
...
render: function() {
    return (
        <div id="page">
            <Node if={this.state.banner}
                  then={<div id="banner">{this.state.banner}</div>} />
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}
2
répondu Gordon Freeman 2016-01-08 23:15:52

j'utilise un raccourci plus explicite: une Expression de fonction immédiatement invoquée (IIFE):

{(() => {
  if (isEmpty(routine.queries)) {
    return <Grid devices={devices} routine={routine} configure={() => this.setState({configured: true})}/>
  } else if (this.state.configured) {
    return <DeviceList devices={devices} routine={routine} configure={() => this.setState({configured: false})}/>
  } else {
    return <Grid devices={devices} routine={routine} configure={() => this.setState({configured: true})}/>
  }
})()}
2
répondu jsdario 2016-12-12 16:54:43

j'ai fait https://www.npmjs.com/package/jsx-control-statements pour le rendre un peu plus facile, fondamentalement, il vous permet de définir <If> conditionnels comme des étiquettes et puis les compile dans les ifs ternaires de sorte que le code à l'intérieur du <If> n'est exécuté que si la condition est vraie.

1
répondu Alex Gilleran 2015-02-26 23:04:53

Il ya aussi une version vraiment propre d'une ligne... { ce.accessoires de jeu.produit.titre || "Sans Titre" }

c'est à dire:

render: function() {
            return (
                <div className="title">
                    { this.props.product.title || "No Title" }
                </div>
            );
        }
1
répondu max kaplan 2015-11-09 22:26:14

j'ai fait https://github.com/ajwhite/render-if récemment pour rendre en toute sécurité les éléments seulement si le prédicat passe .

{renderIf(1 + 1 === 2)(
  <span>Hello!</span>
)}

ou

const ifUniverseIsWorking = renderIf(1 + 1 === 2);

//...

{ifUniverseIsWorking(
  <span>Hello!</span>
)}
1
répondu Atticus 2016-02-05 05:00:28

vous pouvez inclure des éléments en utilisant l'opérateur ternaire comme suit:

render: function(){

         return <div id="page">

                  //conditional statement
                  {this.state.banner ? <div id="banner">{this.state.banner}</div> : null}

                  <div id="other-content">
                      blah blah blah...
                  </div>

               </div>
}
1
répondu mada-g 2016-03-12 13:14:08

vous pouvez utiliser une fonction et retourner le composant et garder mince la fonction de rendu""

class App extends React.Component {
  constructor (props) {
    super(props);
    this._renderAppBar = this._renderAppBar.bind(this);
  }

  render () {
    return <div>
      {_renderAppBar()}

      <div>Content</div>

    </div>
  }

  _renderAppBar () {
    if (this.state.renderAppBar) {
      return <AppBar />
    }
  }
}
1
répondu pedronalbert 2016-06-12 13:08:59

Voici mon approche en utilisant ES6.

import React, { Component } from 'react';
// you should use ReactDOM.render instad of React.renderComponent
import ReactDOM from 'react-dom';

class ToggleBox extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // toggle box is closed initially
      opened: false,
    };
    // http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html
    this.toggleBox = this.toggleBox.bind(this);
  }

  toggleBox() {
    // check if box is currently opened
    const { opened } = this.state;
    this.setState({
      // toggle value of `opened`
      opened: !opened,
    });
  }

  render() {
    const { title, children } = this.props;
    const { opened } = this.state;
    return (
      <div className="box">
        <div className="boxTitle" onClick={this.toggleBox}>
          {title}
        </div>
        {opened && children && (
          <div class="boxContent">
            {children}
          </div>
        )}
      </div>
    );
  }
}

ReactDOM.render((
  <ToggleBox title="Click me">
    <div>Some content</div>
  </ToggleBox>
), document.getElementById('app'));

Démo: http://jsfiddle.net/kb3gN/16688 /

j'utilise un code comme:

{opened && <SomeElement />}

qui ne rendra SomeElement que si opened est vrai. Cela fonctionne en raison de la façon dont JavaScript résoudre les conditions logiques:

true && true && 2; // will output 2
true && false && 2; // will output false
true && 'some string'; // will output 'some string'
opened && <SomeElement />; // will output SomeElement if `opened` is true, will output false otherwise

comme React ignorera false , je le trouve très bon moyen de conditionnellement rendre certains éléments.

1
répondu pie6k 2017-02-13 14:17:41

peut-être qu'il aide quelqu'un qui tombe sur la question: tous les rendus conditionnels dans React c'est un article sur toutes les différentes options pour le rendu conditionnel dans React.

plats à emporter Clés de quand utiliser les rendu conditionnel:

* * if-else

  • est le plus fondamental rendu conditionnel
  • débutants
  • utilisation si pour opt-out tôt d'une méthode de rendu en retournant null

* * opérateur ternaire

  • utilisez-le sur une instruction if-else
  • il est plus concis que si-autrement

** logique && operator

  • utilisez-le quand un côté de l'opération ternaire retournerait null

** commutateur de cas

  • verbose
  • ne peut être intégré qu'avec une fonction d'auto-invocation
  • l'éviter, utiliser enums à la place

** énumérations

  • parfait à la carte des états différents
  • parfait à la carte plus d'une condition

* * rendus conditionnels à niveaux multiples / emboîtés

  • les éviter pour le par souci de lisibilité
  • fractionner les composants en composants plus légers avec leur propre Rendu conditionnel simple
  • use hoc

* * HOCs

  • utilisez-les pour protéger le rendu conditionnel
  • composants peuvent se concentrer sur leur objectif principal

* * éléments extérieurs de construction

  • les éviter et être à l'aise avec JSX et JavaScript
1
répondu Robin Wieruch 2017-02-21 22:30:27

avec ES6 vous pouvez le faire avec un simple one-liner

const If = ({children, show}) => show ? children : null

"show" est un booléen et vous utilisez cette classe par

<If show={true}> Will show </If>
<If show={false}> WON'T show </div> </If>
1
répondu Leon 2018-01-20 00:36:18

Je ne pense pas que cela ait été mentionné. C'est comme votre propre réponse, mais je pense que c'est encore plus simple. Vous pouvez toujours retourner les chaînes des expressions et vous pouvez insérer jsx dans les expressions, ce qui permet une expression inline facile à lire.

render: function () {
    return (
        <div id="page">
            {this.state.banner ? <div id="banner">{this.state.banner}</div> : ''}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

<script src="http://dragon.ak.fbcdn.net/hphotos-ak-xpf1/t39.3284-6/10574688_1565081647062540_1607884640_n.js"></script>
<script src="http://dragon.ak.fbcdn.net/hphotos-ak-xpa1/t39.3284-6/10541015_309770302547476_509859315_n.js"></script>
<script type="text/jsx;harmony=true">void function() { "use strict";

var Hello = React.createClass({
  render: function() {
    return (
      <div id="page">
        {this.props.banner ? <div id="banner">{this.props.banner}</div> : ''}
        <div id="other-content">
          blah blah blah...
        </div>
      </div>
    );   
  }
});

var element = <div><Hello /><Hello banner="banner"/></div>;
React.render(element, document.body);

}()</script>
0
répondu Juan Mendes 2016-04-28 12:51:51

j'aime le caractère explicite de Immédiatement Appelé les Expressions de Fonction ( IIFE ) et if-else plus render callbacks et ternary operators .

render() {
  return (
    <div id="page">
      {(() => (
        const { banner } = this.state;
        if (banner) {
          return (
            <div id="banner">{banner}</div>
          );
        }
        // Default
        return (
          <div>???</div>
        );
      ))()}
      <div id="other-content">
        blah blah blah...
      </div>
    </div>
  );
}

il suffit de se familiariser avec la syntaxe IIFE , {expression} est la syntaxe habituelle de React, à l'intérieur de celle-ci il suffit de considérer que vous écrivez une fonction qui s'invoque.

function() {

}()

qui doivent être enveloppés à l'intérieur parens

(function() {

}())
0
répondu Gianluca Esposito 2016-12-19 09:32:08

il y a aussi une technique utilisant render props pour rendre conditionnel un composant. L'avantage est que le rendu n'évaluerait pas tant que la condition n'est pas remplie, ce qui n'est pas inquiétant pour les valeurs null et non définies .

const Conditional = ({ condition, render }) => {
  if (condition) {
    return render();
  }
  return null;
};

class App extends React.Component {
  constructor() {
    super();
    this.state = { items: null }
  }

  componentWillMount() {
    setTimeout(() => { this.setState({ items: [1,2] }) }, 2000);
  }

  render() {
    return (
      <Conditional
        condition={!!this.state.items}
        render={() => (
          <div>
            {this.state.items.map(value => <p>{value}</p>)}
          </div>
        )}
      />
    )
  }
}
0
répondu Farzad YZ 2017-12-19 22:20:34

quand vous devez rendre quelque chose seulement si la condition passée est remplie, vous pouvez utiliser la syntaxe:

{ condition && what_to_render }

le code de cette façon ressemblerait à ceci:

render() {
    const { banner } = this.state;
    return (
        <div id="page">
            { banner && <div id="banner">{banner}</div> }
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

il y a, bien sûr, d'autres façons valables de le faire, tout dépend des préférences et de l'occasion. Vous pouvez apprendre plus de façons sur la façon de faire le rendu conditionnel dans React dans cet article si vous êtes intéressé!

0
répondu Nesha Zoric 2018-02-22 10:38:22

juste pour ajouter une autre option - si vous aimez / tolérez café-script vous pouvez utiliser café-réagir pour écrire votre JSX dans lequel cas si / else déclarations sont utilisables car ils sont des expressions dans café-script et non des déclarations:

render: ->
  <div className="container">
    {
      if something
        <h2>Coffeescript is magic!</h2>
      else
        <h2>Coffeescript sucks!</h2>
    }
  </div>  
-1
répondu Hal 2015-03-27 01:55:53

juste pour étendre la réponse de @Jack Allan avec des références à docs.

la documentation de base React (Quick Start) suggère null dans ce cas. Cependant, booléens, Null, et non défini sont ignorés ainsi, mentionné dans le guide avancé.

-1
répondu Oleg V. 2017-05-09 05:50:41