← TSX pro LAMP vývojáře
kapitola 01

Co je TSX

Tato kapitola vysvětluje, co vlastně znamená TSX, proč vypadá jako HTML uvnitř JavaScriptu/TypeScriptu a proč to není totéž jako klasická PHP šablona, jQuery generování HTML stringů nebo statické HTML.

Cíl kapitoly: získat základní orientaci. Po přečtení by mělo být jasné, co je .tsx soubor, jak souvisí s Reactem, TypeScriptem a JSX, a proč se v moderním frontendu často píše UI právě tímto způsobem.


Krátká definice

TSX znamená:

TypeScript + JSX

Jinými slovy: TSX je syntaxe, ve které můžeš psát TypeScript a zároveň uvnitř něj zapisovat UI strukturou podobnou HTML.

Jednoduchý příklad:

function Hello() {
  return <h1>Ahoj světe</h1>;
}

Na první pohled to vypadá, jako by JavaScriptová funkce vracela HTML. Technicky ale nejde o čisté HTML. Jde o syntaxi, kterou build nástroj přeloží do JavaScriptu, kterému prohlížeč rozumí.


TSX není HTML

Tohle je první důležitá věc.

Když napíšeš:

const title = <h1>Ahoj</h1>;

nevzniká tím rovnou HTML string:

<h1>Ahoj</h1>

Vzniká popis UI, se kterým potom pracuje React.

Dříve se JSX/TSX často vysvětlovalo tak, že se překládá přibližně na:

React.createElement("h1", null, "Ahoj");

Moderní React build nástroje to interně řeší trochu jinak, ale mentální model je pořád podobný:

TSX zápis
→ build nástroj ho přeloží
→ React podle něj vytvoří nebo aktualizuje UI

Důležité je, že TSX je zdrojový zápis pro UI, ne finální HTML dokument.


TSX vs JSX

Možná narazíš na dvě podobné přípony:

.jsx
.tsx

Rozdíl:

JSX = JavaScript + JSX syntaxe
TSX = TypeScript + JSX syntaxe

Příklad JSX:

function UserCard({ name }) {
  return <div>{name}</div>;
}

Příklad TSX:

type UserCardProps = {
  name: string;
};

function UserCard({ name }: UserCardProps) {
  return <div>{name}</div>;
}

V TSX navíc používáš TypeScript typy. To znamená, že můžeš typovat props, stav, data z API, eventy a další věci.

Pro zkušeného back-end vývojáře je TSX většinou lepší než čistý JSX, protože typy výrazně pomáhají udržet větší projekt pod kontrolou.


Co je JSX část

JSX je syntaxe, která umožňuje psát něco jako HTML přímo uvnitř JavaScriptu nebo TypeScriptu.

Příklad:

function App() {
  return (
    <main>
      <h1>Moje aplikace</h1>
      <p>Vítej na stránce.</p>
    </main>
  );
}

Toto není PHP šablona a není to ani HTML soubor. Je to TypeScriptový kód s JSX syntaxí.

Uvnitř můžeš kombinovat:

  • značky podobné HTML,
  • vlastní komponenty,
  • proměnné,
  • podmínky,
  • mapování polí,
  • event handlery.

Například:

function Greeting() {
  const name = "Hynek";

  return <p>Ahoj, {name}</p>;
}

Složené závorky {} znamenají: tady se vyhodnotí JavaScriptový/TypeScriptový výraz.


Co je TypeScript část

TypeScript je nadstavba JavaScriptu, která přidává typy.

JavaScript:

function add(a, b) {
  return a + b;
}

TypeScript:

function add(a: number, b: number): number {
  return a + b;
}

U TSX komponent to znamená, že můžeš jasně říct, jaká data komponenta očekává.

Příklad:

type ProjectCardProps = {
  title: string;
  description: string;
  url: string;
};

function ProjectCard({ title, description, url }: ProjectCardProps) {
  return (
    <article>
      <h2>{title}</h2>
      <p>{description}</p>
      <a href={url}>Otevřít projekt</a>
    </article>
  );
}

Když pak komponentě předáš špatná data, TypeScript tě může upozornit ještě před tím, než se chyba projeví v prohlížeči.


Jak se TSX liší od PHP šablony

V PHP můžeš psát například:

<h1><?= $title ?></h1>
<p><?= $description ?></p>

nebo:

<?php foreach ($projects as $project): ?>
  <h2><?= $project['title'] ?></h2>
<?php endforeach; ?>

V TSX by podobný princip vypadal takto:

function ProjectList({ projects }: { projects: Project[] }) {
  return (
    <section>
      {projects.map((project) => (
        <article key={project.id}>
          <h2>{project.title}</h2>
          <p>{project.description}</p>
        </article>
      ))}
    </section>
  );
}

Podobnost:

data se promítají do výsledného UI

Rozdíl:

PHP šablona typicky generuje HTML na serveru pro jeden request

TSX komponenta popisuje UI jako funkci nad daty a stavem
React podle toho UI vytváří a aktualizuje v prohlížeči nebo v rámci frameworku typu Next.js

V PHP často přemýšlíš:

vygeneruj HTML odpověď

V React/TSX světě přemýšlíš:

popiš, jak má UI vypadat pro aktuální data a stav

Jak se TSX liší od jQuery přístupu

V jQuery se často pracovalo procedurálně:

$("#title").text("Ahoj");
$("#box").hide();
$("#items").append("<li>Nová položka</li>");

Tedy:

najdi element
změň ho
přidej HTML
skryj HTML
pověs event handler

V TSX/Reactu se snažíš spíš popsat výsledek:

function Box({ visible }: { visible: boolean }) {
  return (
    <div>
      {visible && <p>Viditelný obsah</p>}
    </div>
  );
}

Neříkáš tedy přímo:

najdi element a skryj ho

ale:

pokud visible je true, zobraz tento kus UI
pokud visible je false, tento kus UI vůbec nevyrenderuj

To je jeden z hlavních mentálních rozdílů.


TSX jako zápis stromu UI

UI si můžeš představit jako strom.

Například:

function App() {
  return (
    <main>
      <Header />
      <ProjectList />
      <Footer />
    </main>
  );
}

Stromově:

App
└── main
    ├── Header
    ├── ProjectList
    └── Footer

Komponenty můžeš skládat do sebe podobně jako funkce nebo šablony.

Menší komponenta:

function Header() {
  return <header>Moje stránka</header>;
}

Větší komponenta:

function App() {
  return (
    <>
      <Header />
      <main>Obsah stránky</main>
    </>
  );
}

Komponenta je v základu funkce, která vrací UI.


Malá písmena vs velká písmena

V TSX je důležitý rozdíl mezi malými a velkými písmeny.

HTML elementy se píšou malým písmenem:

<div>
  <h1>Nadpis</h1>
</div>

Vlastní komponenty se píšou velkým písmenem:

<ProjectCard />
<UserProfile />
<MainNavigation />

React podle toho pozná, jestli jde o běžný HTML element, nebo o tvoji komponentu.

Příklad:

function ProjectCard() {
  return <article>Projekt</article>;
}

function App() {
  return <ProjectCard />;
}

Kdybys komponentu napsal malým písmenem, React by ji bral jako HTML tag, což není to, co chceš.


TSX soubor v projektu

Soubor s příponou .tsx se používá tam, kde kombinuješ TypeScript a JSX syntaxi.

Typické názvy:

App.tsx
page.tsx
layout.tsx
ProjectCard.tsx
Button.tsx

Soubory .ts se používají pro TypeScript bez JSX/TSX zápisu.

Příklad .ts souboru:

export function formatPrice(value: number): string {
  return `${value} Kč`;
}

Příklad .tsx souboru:

export function Price({ value }: { value: number }) {
  return <span>{value} Kč</span>;
}

Jednoduché pravidlo:

když soubor vrací nebo obsahuje JSX/TSX značky, použij .tsx

když obsahuje jen logiku, typy, helpery nebo konfiguraci bez JSX, použij .ts

TSX a React

TSX se nejčastěji používá s Reactem. React je knihovna pro tvorbu uživatelského rozhraní.

TSX je syntaxe. React je knihovna, která s tímto zápisem pracuje.

Zjednodušeně:

TSX
→ způsob, jak zapisuješ UI

React
→ knihovna, která podle tohoto zápisu vytváří a aktualizuje UI

Next.js
→ framework nad Reactem, který řeší stránky, routování, metadata, serverové renderování a další věci

Tohle je užitečné rozlišovat:

TypeScript není React
TSX není React
React není Next.js
Next.js používá React
React často používá TSX

TSX a Next.js

V Next.js App Routeru jsou .tsx soubory často přímo stránky.

Například:

app/page.tsx

odpovídá URL:

/

Soubor:

app/learning/page.tsx

odpovídá URL:

/learning

Soubor:

app/learning/tsx-vs-lamp/page.tsx

odpovídá URL:

/learning/tsx-vs-lamp

Uvnitř page.tsx může být komponenta:

export default function Page() {
  return (
    <main>
      <h1>TSX pro LAMP fullstack vývojáře</h1>
      <p>Úvod do školení.</p>
    </main>
  );
}

V Next.js tedy TSX často nepíšeš jen jako malý widget, ale jako celou stránku.


Co se s TSX stane při buildu

Prohlížeč neumí přímo spustit TSX.

Když napíšeš:

function App() {
  return <h1>Ahoj</h1>;
}

build nástroj z toho připraví JavaScript, kterému prohlížeč rozumí.

Zjednodušeně:

App.tsx
↓
TypeScript/React build
↓
JavaScript bundle nebo serverový build
↓
prohlížeč dostane HTML/CSS/JS

Proto nestačí vzít .tsx soubor a otevřít ho přímo v prohlížeči jako .html.

Potřebuješ vývojový server nebo build proces:

npm run dev

nebo:

npm run build

Základní syntaxe TSX

Jeden kořenový element

Komponenta musí vracet jeden kořenový element.

Správně:

function App() {
  return (
    <main>
      <h1>Nadpis</h1>
      <p>Text</p>
    </main>
  );
}

Špatně:

function App() {
  return (
    <h1>Nadpis</h1>
    <p>Text</p>
  );
}

Pokud nechceš přidávat zbytečný <div>, použiješ fragment:

function App() {
  return (
    <>
      <h1>Nadpis</h1>
      <p>Text</p>
    </>
  );
}

Hodnoty přes složené závorky

function Greeting() {
  const name = "Hynek";

  return <p>Ahoj, {name}</p>;
}

Uvnitř {} může být výraz:

<p>{user.isAdmin ? "Admin" : "Uživatel"}</p>

Ne klasický blok s if:

// špatně
<p>{if (user.isAdmin) "Admin"}</p>

Atributy

String atribut:

<input type="email" />

Hodnota z proměnné:

<input value={email} />

Boolean atribut:

<button disabled={isSaving}>Uložit</button>

Event handler:

<button onClick={handleClick}>Klikni</button>

Proč se používá className místo class

V HTML píšeš:

<div class="card"></div>

V TSX píšeš:

<div className="card"></div>

Důvod je historický a technický: class je v JavaScriptu klíčové slovo. JSX/TSX proto používá className.

Podobně:

<label for="email">E-mail</label>

se v TSX píše:

<label htmlFor="email">E-mail</label>

Tyto rozdíly jsou ze začátku otravné, ale rychle se zautomatizují.


Bezpečnost: hodnoty se escapují

Když v TSX vložíš hodnotu:

const name = "<script>alert('xss')</script>";

function App() {
  return <p>{name}</p>;
}

React ji standardně nevloží jako spustitelné HTML, ale jako text. To je bezpečnější než ruční skládání HTML stringů.

V jQuery nebo klasickém JS bylo rizikové používat:

element.innerHTML = userInput;

nebo:

$("#box").html(userInput);

V TSX je běžný zápis:

<p>{userInput}</p>

standardně bezpečnější, protože React hodnotu escapuje.

Pokud bys opravdu potřeboval vložit raw HTML, existuje dangerouslySetInnerHTML, ale už název napovídá, že je potřeba s tím zacházet velmi opatrně.


Malý praktický příklad

Představ si, že chceš zobrazit kartu projektu.

Datový typ:

type Project = {
  id: string;
  title: string;
  description: string;
  url: string;
};

Komponenta:

type ProjectCardProps = {
  project: Project;
};

function ProjectCard({ project }: ProjectCardProps) {
  return (
    <article className="project-card">
      <h2>{project.title}</h2>
      <p>{project.description}</p>
      <a href={project.url}>Otevřít</a>
    </article>
  );
}

Použití:

const project = {
  id: "levnemenu",
  title: "LevnéMenu.cz",
  description: "Denní menu a restaurace přehledně na mapě.",
  url: "https://levnemenu.cz",
};

function App() {
  return <ProjectCard project={project} />;
}

Tady už je vidět několik základních principů:

  • UI je komponenta,
  • komponenta dostává data přes props,
  • data jsou typovaná,
  • výstup vypadá jako HTML, ale je to TSX,
  • hodnoty se vkládají přes {}.

Jak o TSX přemýšlet jako LAMP vývojář

Nejbližší analogie:

PHP šablona:
data + template → HTML

TSX komponenta:
props/state + komponenta → UI

Ale rozdíl je v tom, že TSX komponenta se může v prohlížeči opakovaně přepočítávat podle změny stavu.

Například:

uživatel klikne na tlačítko
↓
změní se stav
↓
React znovu vyhodnotí komponentu
↓
UI se aktualizuje

Není potřeba ručně hledat element a měnit jeho text. Změníš data nebo stav a UI z toho vyplyne.


Co si z této kapitoly odnést

TSX je zápis UI pomocí TypeScriptu a JSX syntaxe. Vypadá podobně jako HTML, ale není to HTML soubor ani HTML string. Je to zdrojový kód, který se při buildu překládá do JavaScriptu.

TSX se nejčastěji používá s Reactem. React podle něj vytváří a aktualizuje uživatelské rozhraní. Frameworky jako Next.js na Reactu staví a používají TSX nejen pro komponenty, ale i pro celé stránky.

Pro LAMP vývojáře je nejdůležitější změna v myšlení: místo ručního generování HTML stringů nebo manipulace s DOMem popisuješ, jak má UI vypadat pro aktuální data a stav.

Základní věta, kterou si zapamatuj:

TSX je TypeScriptový zápis UI, který vypadá jako HTML, ale chová se jako součást JavaScript/React aplikace.

Mini tahák

// komponenta
function App() {
  return <h1>Ahoj</h1>;
}

// hodnota v UI
const name = "Hynek";
<p>{name}</p>;

// vlastní komponenta
<ProjectCard />

// HTML element
<div></div>

// CSS třída
<div className="card"></div>

// label for
<label htmlFor="email">E-mail</label>

// fragment
<>
  <h1>Nadpis</h1>
  <p>Text</p>
</>

// typované props
type ButtonProps = {
  label: string;
};

function Button({ label }: ButtonProps) {
  return <button>{label}</button>;
}

Co bude dál

Teď už víš, co je TSX na základní úrovni. Další kapitola by měla vysvětlit mentální model Reactu/TSX: proč se neprogramuje hlavně stylem „najdi element a změň ho“, ale stylem „změň stav/data a UI se podle toho samo přepočítá“.