React Junior
207 subscribers
37 photos
462 links
Изучение React с нуля
加入频道
JSX

JSX - это нечто среднее между HTML и JS. Большей частью этот формат похож на HTML, но с некоторыми особенностями из JS.

По умолчанию в браузерах он не обрабатывается, поэтому нужен компилятор - Babel. Он преобразует JSX в обычный JavaScript и исполняет его.

По большому счету JSX в React не необходим, все то же самое можно написать прямо на JS (как получается после компиляции). Но этот формат кажется очень удобным, поэтому сразу начнем работать с ним.

Главные особенности работы с JSX:

👉 атрибуты указываются не в kebab-case, а в camelCase, как в JavaScript
👉 вместо class нужно писать className
👉 вместо for (для элементов label) нужно писать htmlFor
👉 обработчики событий на тегах тоже в camelCase

Фрагмент JSX - это обычное JS-выражение, которое можно поместить в переменную и делать с ним другие привычные операции, например, передавать в функции и возвращать из них (как мы делаем в компонентах).

Читать в документации (рус): https://ru.react.js.org/docs/introducing-jsx.html

#началоработы #jsx #документация
Выражения в JSX

Внутри JSX можно использовать различные JS-конструкции и выражения. Для этого предназначены фигурные скобки - все внутри них воспринимается именно как выражение и выполняется. В результате выполнения обычно получается фрагмент JSX или null, если ничего выводить не требуется.

https://codepen.io/furrycat/pen/yLMPKzW?editors=1010

Это можно использовать для условного рендеринга - когда в зависимости от некоторого условия выводится тот или иной фрагмент разметки или компонент (или вообще ничего не выводится).

#началоработы #jsx #документация
👍1
Вывод списков

Чтобы вывести несколько элементов внутри JSX, их нужно просто собрать в массив. Идеальный метод для этого Array.prototype.map. Он принимает любые данные в виде массива и может превратить их в фрагменты JSX. Полученный массив можно записать в переменную, а можно сразу вывести в JSX.

https://codepen.io/furrycat/pen/vYxpJea?editors=0010

Важно: каждый элемент списка должен иметь уникальный ключ (атрибут key).

#началоработы #jsx #примерыкода #документация
Условный рендеринг

Очень часто нужно вывести один или другой компонент в зависимости от некоторого условия - например, ссылку на авторизацию или приветствие, если юзер уже авторизован.

Мы уже разбирались, что в JSX можно использовать любые валидные JavaScript-выражения. В том числе и самые разные условия. Быстро пробежимся по вариантам.

👉 Вне JSX

https://codepen.io/furrycat/pen/YzZLrzE?editors=0010

Мы всегда можем произвести все нужные операции ДО инструкции return (в теле функционального компонента или метода render классового компонента). Здесь можно использовать любые JS-конструкции, включая if и switch.

Вычислив нужный компонент, просто поместите его в переменную и выведите в JSX в return.

👉 Внутри JSX

Внутри JSX можно использовать только ВЫРАЖЕНИЯ, то есть if не подходит. Вместо него подойдут:

☑️ оператор логического сложения &&. Подходит, если вам нужно вывести или скрыть какой-то компонент в зависимости от условия.

https://codepen.io/furrycat/pen/ExWLway?editors=0010

☑️ тернарный оператор. Дает возможность выбрать между двумя вариантами.

https://codepen.io/furrycat/pen/MWpGEwW?editors=0010

Главное, не стремиться все запихнуть в JSX. Большие и сложные выражения лучше выносить в тело функции для лучшей читаемости.

#началоработы #jsx #примерыкода #документация
Можно ли без JSX?

На мой взгляд, JSX - удобный и наглядный формат для представления разметки, но кому-то он может не нравиться. Или же кто-то может не понимать, как это работает.

На самом деле, все очень просто. JSX компилируется в обычный JavaScript код - вызов функции React.createElement() с описанием DOM-узла (тег, атрибуты, дочерние элементы).

Вот здесь можно онлайн поиграть с компилятором JSX. Просто вводите разметку, а Babel выдаст получившийся JSX.

#jsx #подкапотом #документация
Атрибут key в списках

Три правила для правильной установки ключа:

👉 ключ должен быть уникальным В ПРЕДЕЛАХ МАССИВА ЭЛЕМЕНТОВ
👉 не следует использовать в качестве ключа порядковый индекс элемента в массиве
👉 ключ должен находиться именно на том элементе, который возвращается из массива, а не на его потомках

#важно #jsx #ключи #документация
Зачем в списках нужны ключи?

При выводе массива элементов в JSX React просит указать key для каждого элемента. Другими словами, для каждого элемента нужно указать УНИКАЛЬНЫЙ (в пределах массива) идентификатор. React хочет иметь возможность различать эти элементы, зачем это ему?

Для оптимизации. Если вы добавляете в массив новые элементы, не изменяя при этом другие, React хочет просто добавить один элемент в DOM, а не перерисовывать весь список. Но для этого он должен понимать, что можно оставить как есть.

Документация React просит не использовать в качестве ключей порядковые индексы элементов в массиве - и это очевидно. Ведь если новый элемент добавится в начало массива, индексы у всех последующих элементов тоже изменятся, а значит, React должен будет их перерендерить.

Статья (рус): Использование индекса в качестве ключа — это анти-паттерн

#подкапотом #jsx #ключи #ссылки
Необходимые импорты

Важно: JSX - это синтаксический сахар для метода React.createElement(). Поэтому если вы используете JSX-синтаксис, React всегда должен быть в зоне видимости.

#важно #jsx #подкапотом #документация
Синтаксис расширения для передачи пропсов

Так как JSX - это обычный JS, мы можем использовать в нем синтаксис расширения для передачи пропсов как объекта.

https://codepen.io/furrycat/pen/RwpYZaz?editors=0010

Например, компонент ButtonWrapper рендерит внутри себя компонент Button. И вы хотите передать ряд свойств для компонента Button через ButtonWrapper.

Компоненту ButtonWrapper совсем необязательно знать полный список пропсов, чтобы все их передать в Button. Он просто заберет из объекта props все нужные ему свойства, а все остальное передаст в Button.

#примерыкода #jsx #документация
Зачем нужны ключи. Пример с неконтролируемыми элементами

Если вы используете неконтролируемые элементы (https://yangx.top/react_junior/43), React не может полностью отвечать за их состояние. Чтобы избежать проблем, очень важно соблюдать правила, на которые полагается библиотека. Например, не использовать индексы массива в качестве ключей для элементов.

Пример из документации: https://ru.reactjs.org/redirect-to-codepen/reconciliation/index-used-as-key

В примере как раз используются индексы массива и неконтролируемые инпуты для вывода значений. Если вы добавите новый элемент в конец списка, ничего не сломается, так как индексы предыдущих элементов не поменялись.

индекс 0 - элемент с id: 1, значение 1
индекс 1 - элемент с id: 2, значение 2

Но если добавить новый элемент в начало списка, то все индексы пересчитаются.

индекс 0 - элемент с id: 3
индекс 1 - элемент с id: 1, значение 1
индекс 2 - элемент с id: 2, значение 2

Но интерфейс сломался, инпут первого элемента (индекс 0) по-прежнему отображает 1.

Причины такого поведения лежат в механизме согласования изменений, который использует React. О нем поговорим в следующем посте.

#ошибки #jsx #подкапотом #документация #ключи
Рендер-пропсы

Значениями рендер-пропсов являются функции. Но эти функции используются не обычным образом (например, для обработки событий), а для рендера.

В рендер-пропе в компонент передается функция. Компонент вызывает ее в нужном месте своей разметки, передавая ей при необходимости аргументы. Функция выполняется и возвращает фрагмент JSX.

По сути это почти то же самое, что и props.children - дочерние элементы компонента. Кстати, проп children можно указывать явно, и он тоже может быть функцией, то есть рендер-пропом.

Статья из документации (рус.): https://ru.reactjs.org/docs/render-props.html

#рендерпропсы #jsx #документация
Функция как дочерний компонент

Мы уже говорили про рендер-пропсы. Они позволяют передать в компонент рендер-функцию, которая просто вставляется в нужном месте и генерирует разметку.

Тут можно немного затормозить, поэтому захотелось вернуться к этому моменту. На самом деле ничего странного в этом нет. Помним, что JSX - это обычный JavaScript, поэтому в ней можно использовать любые валидные выражения, включая также и вызовы функций.

https://codepen.io/furrycat/pen/oNZQmgm?editors=0010

Вы помещаете вызов функции внутри фигурных скобок. Функция выполняется, возвращает разметку, которая и выводится.

Это позволяет передавать в разметку динамические аргументы.

#примерыкода #jsx #началоработы
Список тегов для более удобного поиска постов

👉 Основные понятия

#компоненты
#jsx
#жизненныйциклкомпонента
#виртуальныйdom
#состояние
#обработкасобытий
#потокданных
#ключи
#формы
#рефы
#hoc
#рендерпропсы
#контекст
#порталы
#хуки
#concurrentmode

👉 Управление состоянием

#управлениесостоянием
#redux
#mobx
#recoil

👉 Работа с ошибками

#обработкаошибок
#предохранители
#отладка
#проверкатипов
#typescript
#строгийрежим

👉 Оптимизация

#оптимизация
#profiler
#ленивыекомпоненты
#purecomponent

👉 Тестирование

#тестирование
#jest
#testinglibrary

👉 Серверный рендеринг

#серверныйрендеринг

👉 Стилизация

#стили
#styledcomponents
#jss
#radium
#shadowdom

👉 Распространенные задачи

#валидацияформ
#роутинг
#обменданными
#rtkquery

👉 Прочее

#документация - материалы из официальной документации
#ссылки - полезные ссылки
#началоработы - базовые знания, необходимые для начала работы
#паттерны - хорошие практики работы с React
#примерыкода - реальные примеры кода для изучения
#важно - моменты, на которые нужно обратить внимание
#ошибки - частые ошибки новичков в React
#вопросы
#подкапотом - невидимая часть React
#подключение - подключение React, а также дополнительных пакетов
#инструменты - полезные инструменты для разработки
#доступность
#проект - организация файлов и другие вопросы уровня целого проекта
#api
#безопасность
#отложено - аспекты уже пройденных тем, временно отложенные
Различия между React и HTML

React - это JavaScript, поэтому в некоторых аспектах его синтаксис отличается от стандартного HTML. Все свойства и атрибуты DOM-элементов должны указываться в camelCase (tabIndex вместо tabindex). aria-* и data-* атрибуты остаются как есть.

* className вместо class
* dangerouslySetInnerHTML вместо innerHTML
* htmlFor вместо for
* onChange вместо onInput - для обработки ввода в реальном времени
* value для input/textarea/select
* value на теге select вместо атрибутов selected на тегах option
* style в виде объекта

#документация #важно #jsx