Koşullu öğelere sahip olmak ve Facebook React JSX ile KURU tutmak nasıl?


229

İsteğe bağlı olarak bir öğeyi JSX'e nasıl ekleyebilirim? Burada geçirilmiş olması durumunda bileşen içinde olması gereken bir başlık kullanarak bir örnek. Kaçınmak istediğim if ifadesinde HTML etiketleri çoğaltmak zorunda.

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
Sadece bir elseşubeniz yoksa, bu işe yarıyor mu? Ben jsx aşina değilim ...
Tom Fenech

1
Güzel, bu yardımcı oldu. Ayrıca bkz. Github.com/facebook/react/issues/690
Gabriel Florit

Yanıtlar:


151

Afişi tanımsız olarak bırakın ve dahil edilmez.


1
Bu cevabın yanındaki çöplükten başka bir şey düşünemiyorum ... sanki tanrıların üzerine tökezledim
Timmerz

Does nullkadar iyi işi undefined? Ayrıca, spesifikasyonun bu şekilde çalıştığı ve gelecekte kırılması muhtemel olmadığı bir parçası mı?
hippietrail

133

Peki buna ne dersin. Basit bir yardımcı Ifbileşen tanımlayalım .

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

Ve şu şekilde kullanın:

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

GÜNCELLEME: Cevabım popülerleştiğinden, sizi bu çözümle ilgili en büyük tehlike konusunda uyarmak zorunda hissediyorum. Başka bir cevapta belirtildiği gibi, <If />bileşenin içindeki kod , koşulun doğru olup olmadığına bakılmaksızın her zaman yürütülür. Bu nedenle aşağıdaki örnekte durumda başarısız olacaktır bannerolduğu null(ikinci satırda mülkiyet erişimini dikkat edin):

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

Kullanırken dikkatli olmalısınız. Alternatif (daha güvenli) yaklaşımlar için diğer cevapları okumanızı öneririm.

GÜNCELLEME 2: Geriye dönüp bakıldığında, bu yaklaşım sadece tehlikeli değil aynı zamanda umutsuzca hantaldır. Bir geliştiricinin (ben) bildiği kalıpları ve yaklaşımları bir alandan diğerine aktarmaya çalıştığının tipik bir örneğidir, ancak gerçekten işe yaramaz (bu durumda diğer şablon dilleri).

Koşullu bir öğeye ihtiyacınız varsa, bunu şu şekilde yapın:

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

Başka şubeye de ihtiyacınız varsa, üçlü bir operatör kullanın:

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

Çok daha kısa, daha zarif ve güvenli. Her zaman kullanıyorum. Tek dezavantajı, bu else ifkadar kolay dallanma yapamazsınız , ancak genellikle bu yaygın değildir.

Her neyse, bu JavaScript'teki mantıksal işleçlerin çalışması sayesinde mümkündür . Mantıksal operatörler bunun gibi küçük numaralara bile izin verir:

<h3>{this.state.banner.title || 'Default banner title'}</h3>

1
Teşekkürler. Bu github.com/facebook/react/issues/690 okunmasını tavsiye ederim Bu bağlantı, bu sorunun altındaki yorumlarda yayınlanmıştır ve çözümümü gönderdikten sonra fark ettim. Kontrol ederseniz, bazı adamlar bu çözümden de bahseder, ancak önermez. Şahsen, en azından OP'nin durumunda, tamam olduğunu düşünüyorum, ancak bu yolun mükemmel olmadığı doğrudur (örneğin, başka bir şube tanımlamanın güzel bir yolu yoktur). Her neyse, okumaya değer.
tobik

1
Bunun hala en son sürüm olarak çalışıp çalışmadığından emin değilim, döndürülen değerin a olmasını gerektirirReactElement
srph

Sadece başka bir elemanla sarın <span>veya <div>.
tobik

<noscript> <tr> için alt öğe olarak kabul edilemediğinden, bir <td> veya <table> içinde boş hale getirmek için bunu kullanmaya çalıştığımda sorun var. Aksi takdirde benim için iyi çalışıyor.
Green Su

1
Bunu yapacaksanız, oldukça iyi bir transpilasyon yöntemi vardır: npmjs.com/package/jsx-control-statements
steve

82

Şahsen, gerçekten ( JSX In Depth ) içindeki üçlü ifadelerin ReactJs standartlarına uyan en doğal yol olduğunu düşünüyorum.

Aşağıdaki örneğe bakın. İlk bakışta biraz dağınık ama oldukça iyi çalışıyor.

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

Not: köşeli ayraçlar bileşen döndürmeyle aynıdır, bu nedenle içeriğinizin bir <div> </div> ile çevrelenmesi gerekir.
JoeTidee

@Chiedo neden popüler cevabı tercih ediyorsunuz? Bu harika çalışıyor gibi görünüyor.
Kardan Adam

2
@moby Popüler yanıtın daha dinamik olduğunu ve daha temiz bir oluşturma işleviyle sonuçlandığını düşünüyorum. Bu yaklaşımla, birden fazla koşulunuz varsa ne olur? Artık bu garip formatla iç içe geçme deliliğiniz olacak ve koşullara bağlı olarak iki ayrı alanın aynı değişikliklere ihtiyacı varsa, şimdi koşullu yeniden yazmanız gerekiyor. Sadece benim fikrim olsa! :)
Chiedo

ilgili bir sayfa da oldukça kullanışlıdır: facebook.github.io/react/docs/…
Neil

46

Ayrıca şöyle yazabilirsiniz

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

Eğer senin state.bannerolduğu nullveya undefined, durumun sağ tarafı atlanır.


41

IfKod bloğu çünkü tarzı bileşeni tehlikelidir hep idam bakılmaksızın durumun. Örneğin, bu boş özel durumuna neden bannerolduğu 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>
  );
}

Başka bir seçenek de satır içi işlev kullanmaktır (özellikle else ifadeleriyle yararlıdır):

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

Tepki sorunlarından başka bir seçenek :

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
Şimdiye kadarki tüm çözümler arasında, satır içi işlev en zarif ve basit görünüyor. Dikkat edilmesi gereken bir şey var mı?
suryasankar

22

&& + kod stili + küçük bileşenler

Bu basit test sözdizimi + kod stili kuralları + küçük odaklı bileşenler benim için en okunabilir seçenek. Sadece false, 0veya gibi falsy değerlerine özel dikkat etmeniz gerekir "".

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

gösterim yapmak

ES7 stage-0 do notasyonu sözdizimi de çok güzel ve IDE'm doğru bir şekilde desteklediğinde kesinlikle kullanacağım:

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}/>
}

Daha fazla ayrıntı burada: ReactJs - "If" bileşeni oluşturmak ... iyi bir fikir?


Ücretsiz temel olmayan bilgiler: birincisi denirshort-circuit syntax
sospedra

1
@Deerloper Bilgisayar okullarında öğrendiğimiz ilk şeylerden biri olan && ve & arasındaki farktır, ancak bazı insanlar bilmeyebilir, bu yüzden daha fazla açıklama yapmak kötü bir fikir değildir: en.wikipedia.org/wiki/Short-circuit_evaluation
Sebastien Lorber

Doğru, ama bunu klasik koşullu ifadelerin bir parçası olarak öğretiyorlar. React bileşenini oluşturmak için kısa devreyi kullanma konusunda şaşkın bir sürü insan buldum;)
sospedra

22

Basit, bir işlev oluşturun.

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

Bu şahsen takip ettiğim bir model. Kodu gerçekten temiz ve kolay anlaşılır hale getirir. Dahası Banner, çok büyürse (veya başka yerlerde yeniden kullanılırsa) kendi bileşenine yeniden bakmanıza izin verir .



11

Yanıtlarda daha önce belirtildiği gibi, JSX size iki seçenek sunuyor

  • Üçlü operatör

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

  • Mantıksal bağlantı

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


Ancak, bunlar işe yaramaz price == 0 .

İlk durumda JSX yanlış dalı oluşturacak ve mantıksal birleşme durumunda hiçbir şey görüntülenmeyecektir. Özellik 0 olabilirse, JSX'inizin dışındaki if ifadelerini kullanın.


Bu bir JSX sorunu değil. Durumun kendisi, düz JS'de bile aynı şekilde davranırdı. Herhangi bir sayı istiyorsanız typeof(this.state.price) === "number", koşul olarak kullanın (her iki varyasyonda).
Kroltan

8

Bu bileşen, "if" dalı içinde birden fazla öğeniz olduğunda çalışır:

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

Kullanımı:

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 birisi bu bileşenlerin kod okumak için iyi olmadığını düşünüyor. Ama bence, javascript ile Html daha kötü


Buradaki If yanıtı gibi, bu görüntülenmese bile yanlış koşulu yürütür.
Keegan 82

3

Çoğu örnek, koşullu olarak oluşturulan bir "html" satırına aittir. Koşullu olarak oluşturulması gereken birden fazla satırım olduğunda bu benim için okunabilir görünüyor.

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

İlk örnek iyi çünkü nullşartlı olarak şunun gibi başka içerikler oluşturabiliriz:{this.props.showContent ? content : otherContent}

Ancak içeriği göstermeniz / gizlemeniz gerekiyorsa, Booleans, Null ve Unndefined Are Ignored

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

React bileşeni varsa başka bir çözüm daha vardır :

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

Daha açık bir kısayol kullanıyorum: Hemen Çağırılan İşlev İfadesi (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

Ayrıca gerçekten temiz bir satır sürümü var ... {this.props.product.title || "Başlık yok" }

yani:

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

Yukarıdaki örneğimle çalışıyor mu? Banner desteği yoksa banner div nerede görünmemelidir?
Jack Allan

1

Son zamanlarda sadece yüklem geçerse öğeleri güvenli bir şekilde oluşturmak için https://github.com/ajwhite/render-if yaptım .

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

veya

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

//...

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

1

Üçlü operatörü kullanarak şu şekilde koşullu öğeler ekleyebilirsiniz:

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

Bir işlev kullanabilir ve bileşeni döndürebilir ve oluşturma işlevini ince tutabilirsiniz

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

İşte benim ES6 kullanma yaklaşımım.

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

Demo: http://jsfiddle.net/kb3gN/16688/

Gibi kod kullanıyorum:

{opened && <SomeElement />}

Bu SomeElementsadece openeddoğru olduğunda gerçekleşir. JavaScript'in mantıksal koşulları nasıl çözdüğü nedeniyle çalışır:

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

Görmezden Reactgeleceği gibi , falsebazı öğeleri koşullu olarak oluşturmanın çok iyi bir yolunu buluyorum.


1

Belki şu soruya rastlayan birine yardımcı olur: Reaksiyondaki Tüm Koşullu Renderler koşullu oluşturma için tüm farklı seçenekler hakkında bir makale.

Hangi koşullu oluşturmanın ne zaman kullanılacağına dair önemli bilgiler:

** if-else

  • en temel koşullu oluşturma
  • başlangıç ​​dostu
  • null döndürerek bir oluşturma yönteminden erken çıkmak için kullan

** üçlü operatör

  • if-else deyiminde kullanın
  • if-else'den daha özlüdür

** mantıksal && operatörü

  • üçlü işlemin bir tarafı null olduğunda

** yer değiştir

  • gereksiz sözlerle dolu
  • yalnızca kendi kendini çağırma işleviyle satır içine alınabilir
  • bundan kaçının, bunun yerine numaralandırmalar kullanın

** numaralandırmalar

  • farklı eyaletleri haritalamak için mükemmel
  • birden fazla koşulu haritalamak için mükemmel

** çok seviyeli / iç içe koşullu yorumlamalar

  • okunabilirlik uğruna bunlardan kaçının
  • bileşenleri kendi basit koşullu oluşturma işlemleriyle daha hafif bileşenlere ayırın
  • HOC'ları kullan

** HOC'lar

  • bunları koşullu oluşturmayı engellemek için kullanın
  • bileşenler ana amaçlarına odaklanabilir

** harici şablon bileşenleri

  • onlardan kaçının ve JSX ve JavaScript ile rahat olun

1

ES6 ile basit bir astar ile yapabilirsiniz

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

"show" bir boolean ve bu sınıfı

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

1
Kötü. Her zaman hesaplanacaktır.
Qwertiy

0

Bundan bahsettiğini sanmıyorum. Bu sizin kendi cevabınız gibi ama bence daha da basit. Her zaman ifadelerden dizeler döndürebilir ve ifadelerin içine jsx yerleştirebilirsiniz, böylece bu satır içi ifadenin okunmasını kolaylaştırır.

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

Hemen Çağrılan İşlev İfadeleri'nin ( IIFE) ve if-elseüzeri render callbacksve 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>
  );
}

Sadece IIFEsözdizimini tanımanız gerekir {expression}, her zamanki React sözdizimidir, içinde sadece kendisini çağıran bir işlev yazdığınızı düşünün.

function() {

}()

parens içine sarılması gereken

(function() {

}())

0

Kullanarak bir tekniği de vardır sahne işlemek koşullu bir bileşen kılmak için. Yararı, koşul karşılanıncaya kadar değerlendirmenin sonuç vermemesi, boş ve tanımsız değerler için endişelenmemesidir .

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

Yalnızca geçirilen koşul yerine getirilmişse bir şey oluşturmak zorunda olduğunuzda, sözdizimini kullanabilirsiniz:

{ condition && what_to_render }

Bu şekilde kod şöyle görünecektir:

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

Elbette, bunu yapmanın başka geçerli yolları da var, hepsi tercihlere ve kutlamaya bağlı. İlgileniyorsanız , bu makalede React'ta koşullu oluşturmanın nasıl yapılacağı hakkında daha fazla bilgi edinebilirsiniz !


-1

Sadece başka bir seçenek eklemek için - kahve komut dosyasını beğenirseniz / tolere ederseniz, JSX'inizi yazmak için kahve reaksiyonunu kullanabilirsiniz; bu durumda, / komutları kahve komut dosyasında ifadeler olduğu gibi ifadeler kullanılabilirse:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.