Lekce 1.2

Co JSX skutečně dělá?

Pokud byste byli dotázáni "Co je React komponenta?", vaše první instinkt by mohl být říct: "Funkce, která vrací nějaké UI." Tato odpověď není úplně špatná — ale není ani technicky správná.

Co se naučíte
  • Přesná definice React komponenty
  • Rozdíl mezi JSX a HTML
  • Pravidla a zvláštnosti JSX syntaxe
  • Jak JSX kompiluje do JavaScriptu
  • Praktické příklady JSX transformací

Přesnější definice je:

React komponenta je funkce, která vrací popis UI

Tento rozdíl je důležitý, protože React komponenty nevracejí doslovné HTML.

Nemůžeme dát skutečné HTML do JavaScriptu — takže co přesně vracíme?

Seznamte se s JSX

JSX je "HTML-ová" syntaxe, která vám umožňuje psát značky uvnitř vašich JavaScript souborů. Vypadá to jako HTML, ale ve skutečnosti je to syntaktický cukr, který se kompiluje do čistého JavaScriptu při sestavování.

Než se dostaneme k tomu, co JSX skutečně je, pojďme nejprve prozkoumat některá důležitá pravidla, zvláštnosti a úskalí, které by měl znát každý React vývojář.

Víceřádkové JSX a past ASI

Časté rané zmatení nastává při vracení víceřádkového JSX:

jsx
export default function WhatIsJSX() {
  return <main>
    <h1>This is JSX</h1>
    <h2>JSX <i>looks</i> like HTML</h2>
    <h4>(but it's not)</h4>
    <p>
      JSX is inspired by HTML and allows you to
      write HTML-ish looking syntax inside your
      React Components.
    </p>
  </main>
}

To funguje, ale vypadá to divně — otevírací <main> je na stejném řádku jako return.

Možná byste to zkusili naformátovat přirozeněji:

jsx
export default function WhatIsJSX() {
  return
    <main>...</main>
}

Ale to selže kvůli jemnému problému v JavaScriptu:

Automatické vložení středníku (ASI) vloží středník hned za return.

JavaScript to interpretuje jako:

javascript
return;

Oprava je standardní JSX vzor:

jsx
return (
  <main>
    ...
  </main>
)

Můžete vrátit pouze jeden prvky nejvyšší úrovně

Zvažte:

jsx
export default function Authors() {
  return (
    <h2>Authors</h2>
    <ul>
      <li>Tyler</li>
      <li>Ben</li>
      <li>Alex</li>
    </ul>
  )
}

To vypadá platně… dokud React nevyhodí:

Sousední JSX elementy musí být zabaleny v uzavírajícím tagu

Musíte vrátit jeden prvek nejvyšší úrovně.

Mohli byste vše zabalit do <div>:

jsx
return (
  <div>
    <h2>Authors</h2>
    <ul>...</ul>
  </div>
)

Ale teď jste zavedli zbytečnou značku.

Čisté, sémantické řešení je:

React.Fragment

jsx
return (
  <React.Fragment>
    <h2>Authors</h2>
    <ul>...</ul>
  </React.Fragment>
)

Nebo jeho zkratka:

jsx
<>
  <h2>Authors</h2>
  <ul>...</ul>
</>

Samozavírací tagy se musí explicitně zavřít

V HTML je to v pořádku:

html
<img src="avatar.png">

Ne v JSX.

JSX vyžaduje, aby samozavírací tagy obsahovaly /:

jsx
<img />
<input />
<br />

Takže:

jsx
<img src="search.png" alt="search icon" />
<br />
<input name="term" type="text" />

class → className a další rozdíly v atributech

Nemůžete napsat:

jsx
<img class="avatar" />

protože class je rezervované klíčové slovo JavaScriptu.

React používá className místo toho:

jsx
<img className="avatar" />

Stejně tak HTML atributy s pomlčkami musí být camelCase:

jsx
<rect strokeWidth="5" fillOpacity="0.5" />

Používání výrazů v JSX

Jakýkoli JavaScript výraz musí být zabalen v {}:

jsx
<h1>Hello, {name}</h1>
<p>Today is {new Date().toLocaleDateString()}</p>
<p>{2 + 2}</p>

Zobrazení ničeho: Vrácení null

Komponenta může nezobrazit nic vrácením null:

jsx
if (isLoading()) {
  return null
}

return <main>...</main>

Podmíněné vykreslování v Reactu

Na rozdíl od Angularu a Vue, React neposkytuje speciální šablonovou syntaxi.

Používá čistý JavaScript:

1. if/else

jsx
if (authed) {
  return <h1>Welcome back!</h1>
} else {
  return <h1>Please log in</h1>
}

2. Ternární operátor

jsx
return authed
  ? <h1>Welcome back!</h1>
  : <h1>Please log in</h1>

3. Ternární operátor uvnitř JSX

jsx
<Logo />
{authed ? <Dashboard /> : <Login />}

4. Logický AND (&&)

jsx
{showWarning() && <Warning />}

Velikost písmen je důležitá

React předpokládá:

  • malá písmena = nativní HTML tagy
  • Velká písmena = vlastní React komponenty

Takže:

jsx
<button />HTML button
<Button /> → your own component

Vykreslování seznamů pomocí .map

V Angularu nebo Vue máte šablonovou syntaxi:

Vue:

html
<li v-for="tweet in tweets">{{ tweet.text }}</li>

Angular:

html
<li *ngFor="let tweet of tweets">{{ tweet.text }}</li>

V Reactu používáte čistý JavaScript:

jsx
<ul>
  {tweets.map(tweet => (
    <li key={tweet.id}>{tweet.text}</li>
  ))}
</ul>

Každý prvek v seznamu musí obsahovat jedinečný klíč, aby React mohl efektivně aktualizovat DOM.

Takže… Co JSX skutečně je?

Tady je část, která většinu lidí překvapí:

JSX není HTML. JSX není ani "skoro HTML". JSX je jen JavaScript.

Při sestavování nástroj jako Babel transformuje toto:

jsx
function Hello() {
  return <h1>Hello World</h1>
}

do tohoto:

javascript
import { jsx as _jsx } from "react/jsx-runtime"

function Hello() {
  return _jsx("h1", { children: "Hello World" })
}

Co prohlížeč vidí, je jen JavaScript.

tl;dr — JSX je JavaScript v převleku.

Shrnutí

Pochopení JSX je klíčové pro vývoj v Reactu. Pamatujte:

  • JSX je syntaktický cukr, který se kompiluje do JavaScriptu
  • React komponenty vracejí popisy UI, ne doslovné HTML
  • JSX má specifická pravidla (samozavírací tagy, className, atd.)
  • Podmíněné vykreslování používá čistý JavaScript, ne speciální syntaxi
  • Velikost písmen rozlišuje HTML tagy od React komponent