Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке JSX у React?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**JSX** - це розширення синтаксису JavaScript, яке дозволяє писати HTML-подібну розмітку у JS-файлах. Babel перетворює її на виклики `React.createElement` під час збірки. ```jsx // JSX const elem = <h1 className="title">Hello, {name}!</h1>; // Компілюється у: const elem = React.createElement('h1', { className: 'title' }, 'Hello, ', name, '!'); ``` **Ключове:** JSX - це синтаксичний цукор над `React.createElement`. Результат однаковий в обох випадках.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**JSX** - це розширення синтаксису JavaScript, яке дозволяє писати HTML-подібну розмітку прямо у JS-файлах. Babel перетворює її на виклики `React.createElement` під час збірки. ## Теорія ### TL;DR - JSX - це HTML-синтаксис всередині JavaScript: ті самі знайомі теги, але вирази пишуть у `{}` - Головна перевага: `<div>Hello</div>` замість `React.createElement('div', null, 'Hello')` - Babel конвертує JSX під час збірки, без витрат у рантаймі - Використовуй JSX у кожному React-компоненті; пропускай лише за відсутності бандлера - JSX - це не HTML: атрибути пишуться camelCase (`className`, `onClick`, `htmlFor`) ### Швидкий приклад ```jsx // Без JSX (багатослівно) const elem = React.createElement('h1', null, 'Hello, ', name, '!'); // З JSX (читабельно) const elem = <h1>Hello, {name}!</h1>; // Babel перетворює рядок з JSX у виклик createElement вище. // Результат ідентичний, коду менше. ``` Фігурні дужки `{}` - це перемикач між розміткою та JavaScript. Всередині них - JS-вираз: змінна, тернарний оператор, виклик функції. Звичайний текст за межами дужок залишається буквальним текстом. ### Головна відмінність від HTML JSX схожий на HTML, але відрізняється у трьох речах. Атрибути пишуться camelCase (`className` замість `class`, `htmlFor` замість `for`). Кожен тег потрібно закривати, включно з одиночними (`<img />`). І можна повертати лише один кореневий елемент. Саме через третє правило з'явився `<>...</>` (React.Fragment) - він обгортає кілька елементів без додаткового вузла у реальному DOM. ### Коли використовувати - Будь-який React-компонент → завжди JSX, без винятків - Динамічні списки → `{todos.map(todo => <li key={todo.id}>{todo.text}</li>)}` - Умовний рендеринг → `{isLoading ? <Spinner /> : <Content />}` - Без бандлера (React через CDN script tag) → `React.createElement` напряму - Server-side rendering → JSX без змін у Node через `ReactDOMServer.renderToString` ### Що робить Babel Плагін `@babel/preset-react` читає JSX під час збірки. Теги з великої літери (`<TodoList />`) стають посиланнями на змінну - твою функцію-компонент. Теги з малої (`<ul>`) стають рядковими літералами. Babel також автоматично екранує вміст, тому JSX-вирази ніколи не вставляються як сирий HTML. Це захищає від XSS за замовчуванням. Обійти можна лише через `dangerouslySetInnerHTML` - і назва навмисно незручна. ### Типові помилки **Оператор `if` всередині JSX** ```jsx // Неправильно - if є оператором, а не виразом return <div>{if (isLoggedIn) <p>Hi</p>}</div>; // помилка парсера // Правильно - тернарний оператор є виразом return <div>{isLoggedIn ? <p>Hi</p> : null}</div>; ``` **Рендеринг масиву об'єктів без перетворення** ```jsx // Неправильно - виводить "[object Object],[object Object]" <ul>{[{name: 'Alice'}, {name: 'Bob'}]}</ul> // Правильно <ul>{[{name: 'Alice'}, {name: 'Bob'}].map(item => <li>{item.name}</li>)}</ul> ``` **Кілька кореневих елементів без Fragment** ```jsx // Неправильно - два елементи на верхньому рівні return ( <h1>Title</h1> <p>Text</p> ); // синтаксична помилка // Правильно return ( <> <h1>Title</h1> <p>Text</p> </> ); ``` **`class` замість `className`** ```jsx // Неправильно - class є зарезервованим словом у JS <div class="container">Content</div> // Правильно <div className="container">Content</div> ``` ### Де зустрічається у продакшені - Next.js: кожен файл у `pages/` або `app/` повертає JSX-компонент - React Native: той самий синтаксис JSX, але інші теги (`<View>`, `<Text>` замість `<div>`, `<p>`) - Remix, Gatsby: серверний рендеринг JSX з тією самою моделлю мислення - Preact: сумісний з JSX з розміром рантайму 3 КБ ### Питання на співбесіді **Q:** Що робить Babel з JSX? **A:** Перетворює кожен JSX-тег на виклик `React.createElement`. `<h1>Hi</h1>` стає `React.createElement("h1", null, "Hi")`. Результат - звичайний JS-об'єкт, що описує тип елемента та його пропси. **Q:** Навіщо фігурні дужки для виразів? **A:** Вони сигналізують "тут JS-режим". `{2 + 2}` рендерить 4. Без дужок `2 + 2` залишається рядком "2 + 2". **Q:** Чи може JSX повертати кілька кореневих елементів? **A:** Ні. Обгортай їх у `<>...</>` (React.Fragment). Fragment не з'являється у реальному DOM. **Q:** Яка різниця між атрибутами JSX і HTML? **A:** JSX використовує `className` замість `class`, `htmlFor` замість `for`, camelCase обробники подій (`onClick` замість `onclick`). Атрибути JSX чутливі до регістру, атрибути HTML - ні. **Q:** (Senior) Як JSX обробляє spread-пропси і що відбувається при конфлікті ключів? **A:** `<MyComp {...props} color="blue" />` компілюється у `React.createElement(MyComp, Object.assign({}, props, { color: "blue" }))`. Пізніші пропси перекривають ранніші. Якщо `props.color` дорівнює `"red"`, фінальне значення буде `"blue"`. Злиття поверхневе. ## Приклади ### Базовий: від JSX до DOM ```jsx function Greeting({ name }) { return <h1 className="title">Hello, {name}!</h1>; } // Babel компілює return у: // React.createElement('h1', { className: 'title' }, 'Hello, ', name, '!') // Використання: <Greeting name="Alice" /> // Результат: <h1 class="title">Hello, Alice!</h1> ``` Ти пишеш JSX, Babel виконує конвертацію, React будує DOM-вузол. Більше нічого не відбувається. ### Середній: динамічний список з умовним стилем ```jsx function TodoList({ todos }) { return ( <ul> {todos.map(todo => ( <li key={todo.id} className={todo.completed ? 'done' : ''}> {todo.text} </li> ))} </ul> ); } // Використання: // <TodoList todos={[{ id: 1, text: 'Купити молоко', completed: true }]} /> // Результат: <ul><li class="done">Купити молоко</li></ul> ``` Проп `key` обов'язковий при рендерингу списків. React використовує його для відстеження змін між рендерами. Без нього отримаєш попередження у консолі на кожне оновлення.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.