JSX — to rozszerzenie składni JavaScript wzorowane na XML, opracowane przez zespół React do deklaratywnego opisywania interfejsów użytkownika. W przeciwieństwie do silników szablonów, JSX jest kompilowany do zwykłych wywołań funkcji JavaScript, co daje pełną moc języka wewnątrz znaczników. Według React, 2024, JSX jest obsługiwany we wszystkich nowoczesnych frameworkach i bibliotekach React.
Najważniejsze
JSX (JavaScript XML) — rozszerzenie składni JavaScript, po raz pierwszy przedstawione w React w 2013 roku. Pozwala programistom opisywać strukturę interfejsu użytkownika w stylu deklaratywnym, łącząc znaczniki i logikę w jednym pliku.
Przed pojawieniem się JSX programiści używali szablonów tekstowych (Mustache, Handlebars) lub ręcznie tworzyli elementy DOM przez document.createElement. Oba podejścia miały wady: szablony tekstowe nie były sprawdzane pod kątem typów, a ręczne tworzenie DOM było uciążliwe i podatne na błędy.
React wybrał inną ścieżkę — osadzenie znaczników bezpośrednio w kodzie. Ta decyzja wywołała dyskusje w społeczności, ale z czasem stała się standardem. Dziś JSX jest używany nie tylko w React, ale także w SolidJS, Preact, Qwik, a nawet w Vue poprzez wtyczki.
Element JSX wygląda jak znacznik HTML, ale jest osadzony bezpośrednio w JavaScript. Każdy element jest transpilowany do wywołania React.createElement z trzema argumentami: typem elementu, obiektem propsów i elementami potomnymi. Jeden główny element — obowiązkowa zasada: wyrażenie JSX musi zwracać jeden element nadrzędny lub fragment.
import React from 'react';
// Podstawowy JSX - pojedynczy element główny
const element = (
<div className="app">
<h1>Hello, World!</h1>
<p>Welcome to React</p>
</div>
);
Gdy nie jest potrzebny dodatkowy węzeł DOM, użyj React.Fragment lub krótkiej składni <></>. Fragmenty nie tworzą rzeczywistego elementu DOM, a jedynie grupują węzły potomne. Jest to szczególnie przydatne w tabelach i listach, gdzie dodatkowy opakowujący element zakłóciłby strukturę HTML.
function Columns() {
return (
<>
<td>First</td>
<td>Second</td>
</>
);
}
Dowolne wyrażenie JavaScript osadza się w JSX za pomocą nawiasów klamrowych { }. Wewnątrz można używać zmiennych, wywołań funkcji, operatorów trójargumentowych i metod tablic. Renderowanie warunkowe wykonuje się za pomocą operatora trójargumentowego lub logicznego AND.
function Greeting({ name, isLoggedIn }) {
const items = ['Red', 'Green', 'Blue'];
return (
<div>
{/* Expression with variable */}
<h1>Hello, {name}</h1>
{/* Conditional rendering */}
{isLoggedIn ?
<p>Welcome back!</p :
<button>Login</button>
}
{/* Render array */}
<ul>
{items.map(item =>
<li key={item}>{item}</li>
)}
</ul>
</div>
);
}
Kluczowym ograniczeniem jest to, że wewnątrz nawiasów klamrowych można używać tylko wyrażeń, a nie instrukcji. Nie można używać if/else, for, switch — tylko operator trójargumentowy, operatory logiczne i metody tablic. Wywołania funkcji są dozwolone, w tym funkcji strzałkowych.
JSX wizualnie przypomina HTML, ale ma zasadnicze różnice. Atrybuty zapisuje się w camelCase — className zamiast class, onClick zamiast onclick, tabIndex zamiast tabindex. Wynika to z faktu, że JSX jest transpilowany do JavaScript, gdzie myślnik w nazwie właściwości jest niedozwolony.
| HTML | JSX | Przyczyna |
|---|---|---|
class="wrapper" | className="wrapper" | class — słowo zastrzeżone w JS |
onclick="handle()" | onClick={handle} | camelCase dla właściwości JS |
style="color: red" | style={{ color: 'red' }} | Obiekt stylów zamiast tekstu |
<input disabled> | <input disabled={true}> | Jawne określenie atrybutów boolowskich |
Kolejną ważną różnicą są znaczniki samozamykające. W HTML niektóre znaczniki (br, hr, input) mogą pozostać niezamknięte. W JSX wszystkie znaczniki samozamykające muszą mieć ukośnik zamykający: <br />, <input />. Nazwy atrybutów SVG również są konwertowane na camelCase: strokeWidth, fillOpacity.
Przeglądarki nie rozumieją JSX bezpośrednio. Przed wykonaniem kod JSX przechodzi przez transpilator — Babel, TypeScript lub esbuild. Każdy element JSX jest zamieniany na wywołanie createElement lub jsx/runtime.
// Oryginalny JSX
const element = <h1 className="title">Hello</h1>;
// Po transpilacji
const element = React.createElement(
'h1',
{ className: 'title' },
'Hello'
);
Od React 17 pojawiła się nowa transformacja JSX, która nie wymaga importowania React. Automatyczny import jsx-runtime pozwala pisać komponenty bez import React from 'react'. Babel i TypeScript obsługują tę transformację poprzez ustawienie {"runtime": "automatic"}.
Choć JSX kojarzy się z React, inne frameworki również go używają. SolidJS używa JSX z kompilacją do rzeczywistych węzłów DOM, bez Virtual DOM. Preact — lekka alternatywa dla React z pełną obsługą JSX. Vue obsługuje JSX przez @vue/babel-plugin-jsx, choć jego głównym szablonem jest template.
Kluczowa różnica to semantyka wyrażeń. W React wyrażenia JSX są wykonywane przy każdym renderowaniu. W SolidJS JSX jest kompilowany raz, a aktualizacje są śledzone przez sygnały. Wpływa to na wydajność: SolidJS nie wymaga Virtual DOM i reconciliacji, więc renderowanie JSX jest szybsze.
W TypeScript JSX jest obsługiwany na poziomie języka. Pliki z rozszerzeniem .tsx automatycznie obsługują składnię JSX. Typowanie propsów — jedna z głównych zalet TypeScript + JSX: IDE podpowiada oczekiwane atrybuty, typy callbacków i wymagane propsy.
Pisz kod JSX łatwy do czytania i utrzymania. Wydzielaj złożone wyrażenia do osobnych zmiennych lub funkcji — poprawia to czytelność i pozwala testować logikę oddzielnie od znaczników. Używaj fragmentów zamiast zbędnych opakowań div.
Zasada wcięć — przestrzegaj wcięć dla zagnieżdżonych elementów. Każdy poziom zagnieżdżenia to jeden poziom wcięcia. Znacznik zamykający powinien być na poziomie otwierającego. W przypadku długich atrybutów używaj łamania wierszy.
Unikaj funkcji strzałkowych inline w propsach, jeśli są tworzone przy każdym renderowaniu. W takich przypadkach opakuj callback w useCallback lub wynieś funkcję poza komponent. Dziel złożone komponenty na mniejsze — każdy komponent powinien odpowiadać za jedną logiczną jednostkę interfejsu.
Często zadawane pytania
Tak, przez wtyczkę Babel @babel/plugin-transform-react-jsx można skonfigurować JSX dla dowolnej biblioteki. SolidJS, Preact, Nerv i inne frameworki używają JSX z własnym środowiskiem wykonawczym. Dla pełnej niezależności można ustawić pragma na własną funkcję.
class jest słowem zastrzeżonym w JavaScript. JSX jest transpilowany do createElement, gdzie drugim argumentem przekazywany jest obiekt propsów. Właściwość class koliduje ze składnią klas ES6, dlatego React wybrał className.
Użyj tekstów szablonowych lub biblioteki classnames: className={`“btn ${isActive ? 'active' : ''}”`}. Dla złożonej logiki dołącz pakiet npm clsx lub classnames, które przyjmują obiekty i tablice.
JSX obsługuje tylko wyrażenia, nie instrukcje. Dla warunków używaj operatora trójargumentowego, logicznego AND (&&) lub logicznego OR (||). Dla złożonej logiki wydziel warunek do osobnej zmiennej lub funkcji.
Atrybut key pomaga React identyfikować elementy listy podczas ponownego renderowania. Bez klucza React przerysowuje całą listę przy zmianie. Z unikalnym kluczem React ponownie wykorzystuje węzły DOM i zmienia kolejność elementów zamiast je odtwarzać.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również