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>
);
}
27 réponses
il suffit de laisser banner comme étant non défini et il n'est pas inclus.
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>
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>
, 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é.
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>
);
}
&& + 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?
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).
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
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.
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
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>
);
}
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>
);
}
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})}/>
}
})()}
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.
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>
);
}
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>
)}
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>
}
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 />
}
}
}
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.
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
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>
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>
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() {
}())
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>
)}
/>
)
}
}
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é!
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>
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é.