Ehdollinen renderöinti

Komponenttiesi täytyy usein näyttää eri asioita eri tilanteissa. Reactissa voit ehdollisesti renderöidä JSX:ää käyttämällä JavaScript syntaksia kuten if lauseita, && ja ? : operaattoreita.

Tulet oppimaan

  • Miten palauttaa eri JSX:ää riippuen ehdoista
  • Miten sisällyttää tai poissulkea JSX:ää ehdollisesti
  • Yleisiä ehtolauseiden syntakseja, joita kohtaat React-koodipohjissa

JSX:n palauttaminen ehdollisesti

Sanotaan, että sinulla on PackagingList komponentti renderöimässä useita Item komponentteja, jotka voidaan merkitä pakatuiksi tai ei-pakatuiksi:

function Item({ name, isPacked }) {
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Huomaa, että joillain Item komponenteilla on niiden isPacked propsi asetettu arvoon true eikä false. Haluat kuitenkin lisätä valintamerkin (✔) pakattuihin itemeihin jos isPacked={true}.

Voit kirjoittaa tämän if/else lauseena seuraavasti:

if (isPacked) {
return <li className="item">{name}</li>;
}
return <li className="item">{name}</li>;

Jos isPacked propsi on true, tämä koodi palauttaa eri JSX puun. Tällä muutoksella, jotkin kohteista saavat valintamerkin loppuun:

function Item({ name, isPacked }) {
  if (isPacked) {
    return <li className="item">{name}</li>;
  }
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Kokeile muokata mitä palautuu kummassakin tilassa ja katso miten lopputulos muuttuu!

Huomaa miten luot haaralogiikkaa JavaScriptin if ja return lauseilla. Reactissa ohjausvirtaa (kuten ehtoja) käsittelee JavaScript.

Ehdollisesti tyhjän palauttaminen käyttämällä null

Jossain tilanteissa et halua renderöidä yhtään mitään. Esimerkiksi sanotaan, että et halua näyttää pakattuja kohteita ollenkaan. Komponentin täytyy kuitenkin palauttaa jotain. Tässä tilanteessa, voit palauttaa null:

if (isPacked) {
return null;
}
return <li className="item">{name}</li>;

Jos isPacked on tosi, komponentti ei palauta mitään, null:n. Muussa tapauksessa se palauttaa JSX:n renderöitäväksi.

function Item({ name, isPacked }) {
  if (isPacked) {
    return null;
  }
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Käytännössä null:n palauttaminen komponentista ei ole yleistä, sillä se voi yllättää kehittäjää, joka yrittää renderöidä sitä. Useammin sisällytät tai poissuljet komponentin ehdollisesti pääkomponentin JSX:ssä. Tässä miten se tehdään!

JSX:n sisällyttäminen ehdollisesti

Aikaisemmassa esimerkissä hallitsit kumpi (jos kumpikaan!) JSX puu tulisi komponentin palauttaa. Saatoit huomata hieman toistoa renderöinnin ulostulossa:

<li className="item">{name}</li>

on hyvin samanlainen kuin

<li className="item">{name}</li>

Molemmat ehtohaarat palauttavat <li className="item">...</li>:

if (isPacked) {
return <li className="item">{name}</li>;
}
return <li className="item">{name}</li>;

Vaikka toisto ei ole haitallista, se voi tehdä koodistasi hankalempaa ylläpitää. Entä jos haluat muuttaa className:n? Sinun täytyisi tehdä se kahdessa paikassa koodissasi! Tällaisessa tilanteessa voisit ehdollisesti sisällyttää vähän JSX tehdäksesi koodistasi enemmän kuivaa (engl. DRY.)

Ehdollinen (ternary) operaattori (? :)

JavaScriptissa on kompakti tapa kirjoittaa ehtolauseke — conditional operator taikka “ternary operaattori.”

Tämän sijaan:

if (isPacked) {
return <li className="item">{name}</li>;
}
return <li className="item">{name}</li>;

Voit kirjoittaa tämän:

return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);

Voit lukea sen kuin “jos isPacked on tosi, sitten (?) renderöi name + ' ✔', muussa tapauksessa (:) renderöi nimi.”)

Syväsukellus

Vastaavatko nämä kaksi esimerkkiä toisiaan täysin?

Jos sinulla on taustaa olio-ohjelmoinnista, saatat olettaa, että kaksi yllä olevaa esimerkkiä ovat hienovaraisesti erilaisia, koska yksi niistä voi luoda kaksi erilaista “instanssia” <li> elementistä. Mutta JSX elementit eivät ole “instansseja”, sillä ne eivät ylläpidä sisäistä tilaa eivätkä ne ole aitoja DOM-solmuja. Ne ovat kevyitä kuvauksia, kuten pohjapiirustuksia. Joten nämä kaksi esimerkkiä ovat itse asiassa täysin toisiaan vastaavia. Tilan säilyttäminen ja nollaus menee syvemmälle siihen miten kaikki tämä toimii.

Sanotaan, että haluat kääriä lopullisen kohteen tekstin toiseen HTML tagiin, kuten <del>:iin yliviivataksesi sen. Voit lisätä enemmän rivinvaihtoja ja sulkeita, jotta on helpompi upottaa enemmän JSX koodia kussakin tapauksessa:

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {isPacked ? (
        <del>
          {name + ' ✔'}
        </del>
      ) : (
        name
      )}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Tämä tyyli toimii hyvin yksinkertaisiin ehtolauseisiin, mutta käytä sitä maltillisesti. Jos komponenttisi sotkeutuvat liian monen sisäkkäisen ehdollisten merintöjen kanssa, hatkitse niiden irroittaminen lapsikomponenteiksi, koodin siistimiseksi. Reactissa merkintäkoodi on osa koodiasi, joten voit käyttää ominaisuuksia kuten muuttujia ja funktioita sekavien lausekkeiden siistimiseksi.

Looginen AND operaattori (&&)

Toinen yleinen lyhytoperaatio, johon törmäät on JavaScriptin looginen AND (&&) operaattori. React komponenttien sisällä tulee usein tilainteita, joissa haluat renderöidä jotain JSX:ää kun ehto on tosi, tai jättää renderöimättä muutoin. Käyttämällä && operaattoria voit ehdollisesti renderöidä valintamerkin vain jos isPacked on true:

return (
<li className="item">
{name} {isPacked && '✔'}
</li>
);

Voit lukea tämän kuin “jos isPacked, sitten (&&) renderöi valintamerkki, muussa tapauksessa, älä renderöi mitään.”

Tässä se toiminnassa:

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✔'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

JavaScriptin && lauseke palauttaa oikean puolimmaisen arvon (tässä tapauksessa valintamerkin) jos vasen puoli (ehtomme) on true. Mutta jos ehto on false, koko lausekkeesta tulee false. React käsittää false:n kuin “aukon” JSX puussa, juuri kuten null tai undefined, eikä se renderöi mitään sen kohdalle.

Sudenkuoppa

Älä aseta numeroita && lausekkeen vasemmalle puolelle.

Testatakseen ehtolausetta, JavaScript automaattisesti muuttaa vasemman puolen totuusarvoksi. Kuitenkin, jos vasen puoli on 0, niin silloin koko lauseke saa sen arvokseen (0), ja React mielellään renderöi 0:n tyhjän tilalle.

Yleinen väärinkäsitys on kirjoittaa koodia kuten messageCount && <p>New messages</p>. On helppoa olettaa, ettei se renderöi mitään kun messageCount on 0, mutta se oikeasti renderöi luvun 0 itsessään!

Tämän korjataksesi, tee vasemmasta puolesta totuusarvo: messageCount > 0 && <p>New messages</p>.

JSX:n määrittäminen muuttujaan ehdollisesti

Kun lyhytoperaatiot astuvat koodin kirjoittamisen eteen, kokeile käyttää if lausetta ja muuttujaa. Voit uudelleenmääritellä muuttujia, jotka on esitelty käytten let:iä, joten voit aloittaa tarjoamalla oletussisällön, jota haluat näyttää:

let itemContent = name;

Käytä if lausetta uudelleenmärittelemään JSX-lause muotoon itemContent jos isPacked on true:

if (isPacked) {
itemContent = name + " ✔";
}

Aaltosulkeet avaavat “ikkunan takaisin JavaScriptiin”. Upota muuttuja aaltosulkeilla palautetussa JSX puussa,sisentäen aiemmin laskettu lause JSX:n sisässä:

<li className="item">
{itemContent}
</li>

Tämä tyyli on kaikista monisanainen, mutta se on myös joustavin. Tässä se vielä toiminnassa:

function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = name + " ✔";
  }
  return (
    <li className="item">
      {itemContent}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Kuten aiemmin, tämä toimii sekä teksteille, mutta myös mielivaltaiselle JSX:lle:

function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = (
      <del>
        {name + " ✔"}
      </del>
    );
  }
  return (
    <li className="item">
      {itemContent}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Mikäli JavaScript ei ole tuttua, nämä tyylit voivat tuntua ylivoimaisilta aluksi. Kuitenkin niiden oppiminen helpottavat sinua lukemaan ja kirjoittamaan mitä tahansa JavaScript koodia — eikä vain React komponentteja! Valitse aluksi yksi jota suosit ja sitten viittaa takaisin tähän oppaaseen mikäli unohdat miten muut toimivatkaan.

Kertaus

  • Reactissa ohjaat haaralogiikkaa JavaScriptilla.
  • Voit palauttaa JSX-lauseen ehdollisesti käyttäen if-lausetta.
  • Voit ehdollisesti tallentaa jotain JSX:ää muuttujaan ja sisällyttää sen toisen JSX:n sisään käyttäen aaltosulkeita.
  • JSX:ssä, {cond ? <A /> : <B />} tarkoittaa “jos cond, renderöi <A />, muutoin <B />.
  • JSX:ssä, {cond && <A />} tarkoittaa “jos cond, renderöi <A />, muutoin ei mitään”.
  • Lyhytoperaatiot ovat yleisiä, mutta sinunu ei tarvitse käyttää niitä jos suosit tavallista if lausetta.

Haaste 1 / 3:
Näytä kuvake keskeneräisille kohteille hyödyntämällä ? :

Käytä ehdollista operaattoria (cond ? a : b) renderöidäksesi ❌ jos isPacked ei ole true.

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✔'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}