JSXにオプションで要素を含めるにはどうすればよいですか?これは、渡された場合にコンポーネント内にあるべきバナーを使用した例です。私が避けたいのは、ifステートメントでHTMLタグを複製する必要があることです。
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>
);
}
未定義であるとしてバナーを残すだけで、それは含まれません。
これはどうですか。簡単なIf
コンポーネントを定義しましょう。
var If = React.createClass({
render: function() {
if (this.props.test) {
return this.props.children;
}
else {
return false;
}
}
});
そしてこれを次のように使ってください。
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>
);
}
更新:私の答えが一般的になるにつれて、この解決策に関連した最大の危険性について警告する義務があると感じます。別の回答で指摘されているように、<If />
コンポーネント内のコードは、条件が真か偽かにかかわらず常に実行されます。したがって、次の example は、banner
がnull
の場合には失敗します(2行目のプロパティアクセスに注意してください)。
<If test={this.state.banner}>
<div id="banner">{this.state.banner.url}</div>
</If>
使用するときは注意が必要です。私は別の(より安全な)アプローチのための他の答えを読むことを勧めます。
UPDATE 2:振り返ってみると、このアプローチは危険であるだけでなく、必然的に面倒です。これは、開発者(私)が自分の知っているパターンやアプローチをある領域から別の領域に転送しようとしたが、実際にはうまくいかない場合(この場合は他のテンプレート言語)の典型的な例です。
条件付き要素が必要な場合は、次のようにしてください。
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>
);
}
Else分岐も必要な場合は、三項演算子を使用してください。
{this.state.banner ?
<div id="banner">{this.state.banner}</div> :
<div>There is no banner!</div>
}
それはずっと短く、よりエレガントで安全です。私はいつも使っています。唯一の不利な点は、else if
分岐を簡単に行うことができないということですが、通常はそれほど一般的ではありません。
とにかく、これはJavaScriptで 論理演算子 がどのように機能するかのおかげで可能です。論理演算子でも、次のような小さなトリックが可能です。
<h3>{this.state.banner.title || 'Default banner title'}</h3>
個人的には、三項表現は http://facebook.github.io/react/tips/if-else-in-JSX.html ReactJの標準に準拠する最も自然な方法です。
次の例を見てください。一見すると少し厄介ですが、かなりうまくいきます。
<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>
あなたはまたそれを書くかもしれません
{ this.state.banner && <div>{...}</div> }
あなたのstate.banner
がnull
またはundefined
の場合、条件の右側はスキップされます。
If
スタイルのコンポーネントは、条件に関係なくコードブロックが常に実行されるため危険です。たとえば、banner
がnull
の場合、これは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>
);
}
もう1つの選択肢は、インライン関数を使用することです(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>
);
}
反応からの別のオプション の問題 :
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>
);
}
簡単です、関数を作ります。
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>
);
}
これは私が個人的にいつも従うパターンです。コードを本当にきれいにして理解しやすくします。さらに、それが大きすぎる(または他の場所で再利用される)場合は、Banner
を独自のコンポーネントにリファクタリングできます。
この簡単なテスト構文+コードスタイルの慣習+小さな集中的なコンポーネントは私にとってそこで最も読みやすいオプションです。 false
、0
、""
のような偽の値には特別な注意を払う必要があります。
render: function() {
var person= ...;
var counter= ...;
return (
<div className="component">
{person && (
<Person person={person}/>
)}
{(typeof counter !== 'undefined') && (
<Counter value={counter}/>
)}
</div>
);
}
ES7のステージ0 do記法の構文もとても素敵です。私のIDEが正しくサポートしている場合は、これを使用します
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}/>
}
実験的なES7のdo
構文は、これを簡単にします。 Babelを使用している場合は、es7.doExpressions
機能を有効にします。
render() {
return (
<div id="banner">
{do {
if (this.state.banner) {
this.state.banner;
} else {
"Something else";
}
}}
</div>
);
}
http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions を参照してください。
すでに回答で述べたように、JSXは2つの選択肢を提示します。
三項演算子
{ this.state.price ? <div>{this.state.price}</div> : null }
論理積
{ this.state.price && <div>{this.state.price}</div> }
しかし、それらはprice == 0
では動作しません。
JSXは最初の場合はfalseブランチをレンダリングし、論理積の場合は何もレンダリングされません。プロパティが0になる可能性がある場合は、JSX以外のifステートメントを使用してください。
このコンポーネントは "if"ブランチの中に複数の要素があるときに動作します。
var Display = React.createClass({
render: function() {
if (!this.props.when) {
return false;
}
return React.DOM.div(null, this.props.children);
}
});
使用法:
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>
);
},
PSこのコンポーネントはコードの読み取りには適していないと考える人がいます。しかし、私の心の中ではJavaScriptを使ったhtmlはもっと悪いです
ほとんどの例は、条件付きでレンダリングされる1行の "html"を使用しています。条件付きでレンダリングする必要がある複数の行がある場合、これは私には分かりやすいようです。
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>
);
}
null
の代わりに{this.props.showContent ? content : otherContent}
のような他のコンテンツを条件付きでレンダリングできるので、最初の例は良いです。
ただし、コンテンツを表示/非表示にする必要がある場合は、 Booleans、Null、およびUndefinedが無視されるため 、これはさらに優れています。
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>
);
}
私はもっと明示的なショートカットを使用します。即時起動関数式(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})}/>
}
})()}
別の解決策、 if component for 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>
);
}
本当にきれいな一行バージョンもあります...{this.props.product.title || "タイトルなし"}
すなわち:
render: function() {
return (
<div className="title">
{ this.props.product.title || "No Title" }
</div>
);
}
これが私の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'));
デモ: http://jsfiddle.net/kb3gN/16688/
私は次のようなコードを使っています:
{opened && <SomeElement />}
SomeElement
がtrueの場合のみ、それはopened
をレンダリングします。 JavaScriptが論理条件をどのように解決するかによって、うまくいきます。
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
React
はfalse
を無視するので、いくつかの要素を条件付きでレンダリングするのはとても良い方法です。
次のように三項演算子を使用して条件付きで要素を含めることができます。
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>
}
私は https://www.npmjs.com/package/jsx-control-statements を作成してそれをもう少し簡単にします、基本的にそれはあなたが定義することを可能にします<If>
条件式をタグとして使用し、それらを3進数ifにコンパイルして、<If>
内のコードが条件が真の場合にのみ実行されるようにします。
多分それは質問に遭遇する誰かを助ける: Reactのすべての条件付きレンダリング Reactの条件付きレンダリングのためのすべての異なるオプションに関する記事です。
どの条件付きレンダリングを使用するかについての主な注意事項
** if-else
**三項演算子
**論理的な&&演算子
** スイッチケース
**列挙
**マルチレベル/ネスト条件付きレンダリング
** HOC
**外部テンプレートコンポーネント
要素を安全にレンダリングするために、最近私は https://github.com/ajwhite/render-if を作成しました述語はを渡します。
{renderIf(1 + 1 === 2)(
<span>Hello!</span>
)}
または
const ifUniverseIsWorking = renderIf(1 + 1 === 2);
//...
{ifUniverseIsWorking(
<span>Hello!</span>
)}
関数を使用してコンポーネントを返し、レンダリング関数を薄くしておくことができます。
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 />
}
}
}
ES6では、シンプルなワンライナーでそれを実現できます
const If = ({children, show}) => show ? children : null
"show"はブール値なので、このクラスを使用します。
<If show={true}> Will show </If>
<If show={false}> WON'T show </div> </If>
コンポーネントを条件付きでレンダリングするには、レンダリングプロップを使用する方法もあります。利点は、条件が満たされるまでレンダリングが評価されないため、nullおよびの未定義値を心配する必要がないことです。
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>
)}
/>
)
}
}
私はこれが言及されているとは思わない。これはあなた自身の答えのようですが、私はそれがさらに簡単だと思います。あなたはいつでも式から文字列を返すことができ、式の中にjsxをネストすることができるので、これは読みやすいインライン式を可能にします。
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>
渡された条件が満たされている場合にのみ何かをレンダリングする必要がある場合は、次の構文を使用できます。
{ condition && what_to_render }
この方法のコードは次のようになります。
render() {
const { banner } = this.state;
return (
<div id="page">
{ banner && <div id="banner">{banner}</div> }
<div id="other-content">
blah blah blah...
</div>
</div>
);
}
もちろん、これを行うための有効な方法は他にもあります。それはすべて、設定とオカレンス次第です。興味があれば、 この記事 でReactで条件付きレンダリングを行う方法についてもっと学ぶことができます。
if-else
とrender callbacks
よりも、即時呼び出し関数式(IIFE
)と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>
);
}
あなたはIIFE
構文に精通している必要があります、{expression}
は普通のReact構文です、その中でそれ自身がそれ自身を呼び出す関数を書いていると考えてください。
function() {
}()
それは括弧の中に包む必要がある
(function() {
}())