Facebook ReactのJSXで条件付き要素を設定し、DRYを維持するにはどうすればよいですか?


229

オプションで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>
    );
}

3
elseブランチがない場合はどうなりますか?私はjsxに詳しくありません...
Tom Fenech

1
いいですね、これは役に立ちました。参照してくださいgithub.com/facebook/react/issues/690
ガブリエルFlorit

Reactで条件付きレンダリングを実行するためのオプションの完全なリスト:robinwieruch.de/conditional-rendering-react
Robin Wieruch 2017

回答:


151

バナーを未定義のままにしておくと、含まれません。


1
私はその答えの隣にあるゴミ以外は何も考えられません...まるで神々に出会ったかのようです
Timmerz

DOESのnull作品ばかりと同様にundefined?また、仕様の中でこのように機能するため、将来的に機能しなくなる可能性はありませんか?
ヒッピートレイル2017

133

これはどうですか。簡単な支援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 />コンポーネント内のコードは、条件が真か偽かに関係なく常に実行されます。したがって、次のは、bannerisの場合に失敗しnullます(2行目のプロパティアクセスに注意してください)。

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

使用する際は注意が必要です。別の(より安全な)アプローチについては、他の回答を読むことをお勧めします。

更新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ブランチも必要な場合は、3項演算子を使用するだけです。

{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>

1
ありがとう。私はこのgithub.com/facebook/react/issues/690を読むことをお勧めします。このリンクはこの質問の下のコメントに投稿されており、解決策を投稿した後で気づきました。チェックすると、このソリューションについて言及している人もいますが、推奨していません。個人的には、少なくともOPの場合は大丈夫だと思いますが、この方法が完全ではないことは事実です(たとえば、elseブランチを定義するための良い方法はありません)。とにかく、それは読む価値があります。
tobik 2014年

1
わからない、これはまだ最新版として動作するかどうかであることを返された値を必要とするようだReactElement
srph

ただ、他の要素とそれを包む、<span>または<div>
tobik

<noscript>は<tr>の子として受け入れられないため、これを使用して<td>または<table>で空をレンダリングしようとしたときに問題が発生します。それ以外の場合は、私にとってはうまくいきます。
Green Su

1
これを行う場合は、かなり良い翻訳方法があります:npmjs.com/package/jsx-control-statements
steve

82

個人的には、(JSX In Depth)で示されている3 項式は、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>

注:角かっこはコンポーネントの戻り値と同じであるため、コンテンツを<div> </ div>で囲む必要があります。
JoeTidee 2016年

@Chiedoなぜ代わりに人気のある答えを好むのですか?これはうまくいくようです。
雪だるま

2
@moby私は一般的な答えはより動的で、よりきれいなレンダー機能をもたらすと思います。このアプローチで、複数の条件がある場合はどうなりますか?これで、この奇妙な形式で入れ子になっている狂気になり、2つの別々の領域に条件に基づいて同じ変更が必要な場合は、条件をもう一度書き直す必要があります。私の意見だけでも!:)
Chiedo

関連ページも非常に便利です。facebook.github.io/react/docs/...
ニール

46

次のように書くこともできます

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

あなたがいる場合state.bannerであるnullundefined、条件の右側はスキップされます。


41

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>
  );
}

別のオプションは、インライン関数を使用することです(特に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>
  );
}

2
これまでのすべてのソリューションの中で、インライン関数は最もエレガントで簡単です。気をつけるべきことはありますか?
Suryasankar

22

&& +コードスタイル+小さなコンポーネント

この単純なテスト構文+コード形式の規則+小さな集中コンポーネントは、私にとって最も読みやすいオプションです。あなただけのようなfalsy値の特別な世話をする必要があるfalse0または""

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

表記する

ES7のステージ0の記法構文も非常に優れており、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}/>
}

詳細はこちら: ReactJs-「If」コンポーネントの作成...いいアイデアですか?


無料の非基本情報:最初の情報が呼び出されますshort-circuit syntax
sospedra 2017年

1
私は間違いを推測@Deerloper &&と&私たちは、コンピュータの学校で学ぶ最初のものの一つですが、それはより多くの説明を与えることは悪い考えではありませんので、一部の人は知らないかもしれない。en.wikipedia.org/wiki/Short-circuit_evaluation
Sebastien Lorber 2017年

確かに、しかし彼らはそれを古典的な条件文の一部として教えています。短絡回路を使用してReactコンポーネントをレンダリングすることについて、多くの人が混乱していることを発見しました;)
sospedra

22

シンプルで、関数を作成します。

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コンポーネントが大きくなりすぎた場合(または他の場所で再利用された場合)は、独自のコンポーネントにリファクタリングできます。



11

回答ですでに述べたように、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ステートメントを使用します。


これはJSXの問題ではありません。それは状態そのものです。プレーンなJSでも同じように動作します。任意の数値が必要な場合はtypeof(this.state.price) === "number"、条件として使用します(どちらのバリアントでも)。
Kroltan 2016年

8

このコンポーネントは、「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の方が悪い


ここでのIf回答のように、表示されていなくてもfalse条件が実行されます。
キーガン82

3

ほとんどの例は、条件付きでレンダリングされる「html」の1行を使用しています。条件付きでレンダリングする必要がある複数の行がある場合、これは私には読みやすいようです。

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}

ただし、コンテンツを表示/非表示にするだけの場合は、ブール値、Null、および未定義が無視されるため、これはさらに優れています。

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>
  );
}


2

私はより明示的なショートカットを使用します:即時に呼び出される関数式(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})}/>
  }
})()}


1

本当にきれいな一行バージョンもあります... {this.props.product.title || "無題" }

すなわち:

render: function() {
            return (
                <div className="title">
                    { this.props.product.title || "No Title" }
                </div>
            );
        }

上記のサンプルで動作しますか?バナープロップがない場合、バナーdivは表示されませんか?
Jack Allan、

1

最近、https://github.com/ajwhite/render-ifを作成して、述語が合格した場合にのみ要素を安全にレンダリングします。

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

または

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

//...

{ifUniverseIsWorking(
  <span>Hello!</span>
)}

1

次のように、三項演算子を使用して要素を条件付きで含めることができます。

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

関数を使用してコンポーネントを返し、レンダリング関数を薄く保つことができます

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

これが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 />}

これはtrueのSomeElement場合にのみレンダリングされ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、私はそれを条件付きでいくつかの要素をレンダリングするために非常に良い方法を見つけます。


1

多分それは質問に出くわす人を助ける:Reactのすべての条件付きレンダリングすべての異なるオプションについての記事です。

どの条件付きレンダリングをいつ使用するかの重要なポイント:

** if-else

  • 最も基本的な条件付きレンダリングです
  • 初心者フレンドリー
  • nullを返すことにより、レンダーメソッドから早期にオプトアウトする場合に使用します

**三項演算子

  • if-elseステートメントで使用する
  • if-elseよりも簡潔です

**論理&&演算子

  • 三項演算の片側がnullを返す場合に使用します

** スイッチケース

  • 冗長
  • 自己呼び出し機能でのみインライン化できます
  • それを避け、代わりに列挙型を使用してください

**列挙型

  • さまざまな州をマッピングするのに最適
  • 複数の条件をマッピングするのに最適

**マルチレベル/ネストされた条件付きレンダリング

  • 読みやすさのためにそれらを避けてください
  • コンポーネントを独自の単純な条件付きレンダリングでより軽量なコンポーネントに分割する
  • HOCを使用する

** HOC

  • それらを使用して条件付きレンダリングを保護する
  • コンポーネントは主な目的に焦点を合わせることができます

**外部テンプレートコンポーネント

  • それらを避け、JSXとJavaScriptに慣れる

1

ES6では、シンプルなワンライナーでそれを行うことができます

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

"show"はブール値であり、このクラスを使用するには

<If show={true}> Will show </If>
<If show={false}> WON'T show </div> </If>

1
悪い。常に計算されます。
Qwertiy、2018年

0

これは言及されていないと思います。これはあなた自身の答えのようなものですが、もっと簡単だと思います。いつでも式から文字列を返すことができ、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>


0

I直後-呼び出される関数の式(の明示のようなIIFE)およびif-elseオーバーrender callbacksternary 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() {

}())

0

コンポーネントを条件付きでレンダリングするためにレンダープロップを使用する手法もあります。その利点は、条件が満たされるまでレンダーが評価されないため、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>
        )}
      />
    )
  }
}

0

渡された条件が満たされている場合にのみレンダリングする必要がある場合は、構文を使用できます。

{ 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で条件付きレンダリングを行う方法の詳細を学ぶことができます!


-1

別のオプションを追加するだけです-コーヒースクリプトが好き/許容できる場合は、coffee-reactを使用してJSXを記述できます。

render: ->
  <div className="container">
    {
      if something
        <h2>Coffeescript is magic!</h2>
      else
        <h2>Coffeescript sucks!</h2>
    }
  </div>  

-1

ドキュメントへの参照で@Jack Allanの回答を拡張するだけです。

nullそのような場合、Reactの基本(クイックスタート)ドキュメントで提案されています。ただし、ブール値、Null、および未定義無視されます(詳細ガイドで説明)。


明確にするために修正-false、null、undefined、およびtrueは無視しても有効です-facebook.github.io/react/docs/…。ただし、クイックスタートでは、nullをアドバイスすることを好みます。
Oleg V.17年5
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.