React Junior
208 subscribers
37 photos
462 links
Изучение React с нуля
加入频道
Проверка типов

Часто ошибки в приложениях возникают из-за несоответствия ожидаемых и приходящих в рантайме типов данных. Чтобы такие ошибки отлавливать можно использовать специальные инструменты для статической типизации (Flow, TypeScript).

В документации есть отдельный раздел про их подключение: https://ru.reactjs.org/docs/static-type-checking.html

Но есть и более нативное решение - PropTypes, которое хорошо подойдет для небольших проектов.

Раньше библиотека PropTypes поставлялась вместе с React, но теперь она вынесена в отдельный пакет prop-types, который нужно подключить в приложение.

https://codesandbox.io/s/proptypes-react-junior-sze88

Чтобы использовать проверку типов, необходимо объявить для React-компонента статическое свойство propTypes - объект, в котором перечислены правила валидации для разных пропсов.

Если, например, вы укажете, что проп name должен иметь тип PropTypes.string, а придет число, вы увидите ошибку.

Подробнее о PropTypes, различных валидаторах и способах проверки типов для функциональных компонентах в документации: https://ru.reactjs.org/docs/typechecking-with-proptypes.html

Примечание

Функциональность PropTypes доступна только в режиме разработки.

#документация #проверкатипов #примерыкода
Строгий режим

Строгий режим в React активирует дополнительные проверки и предупреждения. Чтобы его включить, используйте компонет React.StrictMode. Действие строгого режима будет распространяться на всех его потомков.

За чем следит строгий режим?

👉 Использование небезопасных методов жизненного цикла.
👉 Использование устаревшего API.
👉 Неожиданные побочные эффекты на этапе рендеринга.

Подробнее о проверках в документации (рус.): https://ru.reactjs.org/docs/strict-mode.html

Примечание

Функциональность StrictMode доступна только в режиме разработки.

#документация #строгийрежим #началоработы
Доступность контента

Обеспечение доступности контента не является необходимой частью обучения React, однако в современном вебе это очень важная тема.

В документации есть отдельная большая статья по обеспечению доступности в React-приложениях (рус.): https://ru.reactjs.org/docs/accessibility.html

Самые важные моменты:

- aria-атрибуты в JSX указываются как есть (с дефисом)
- атрибут for у элемента label нужно указывать как htmlFor
- для управления фокусом на странице используйте рефы

#документация #доступность
React.memo

React.memo - это компонент высшего порядка, который предоставляет сама библиотека.

Его работа похожа на работу метода shouldComponentUpdate, но сравниваются только пропсы (без учета состояния).

Метод React.memo принимает два аргумента: компонент, который нужно обернуть, и функцию areEqual, которая будет сравнивать новый набор пропсов с предыдущим. Функцию сравнения можно не передавать, тогда пропсы будут сравниваться поверхностно (примерно как в PureComponent).

Важно

👉 Функция areEqual должна возвращать true, если пропсы равны, и false, если не равны. (Метод shouldComponentUpdate работает наоборот, но логика кажется понятной по названиям методов).

#документация #hoc #оптимизация
render

Обязательный метод классового компонента, который определяет его представление.

Выходные параметры

👉 Элемент React
👉 Фрагмент React
👉 Портал
👉 Строки и числа
👉 Булево значение или null

Особенности работы

👉 Имеет доступ к пропсам (this.props) и состоянию (this.state) компонента.
👉 Метод render должен быть чистой функцией.
👉 Главная задача метода - сформировать представление документа. Всю логику по возможности следует вынести в другие методы экземпляра компонента. Также следует избегать создания объектов или функций в этом методе, так как при каждом перерендере они будут создаваться заново.
👉 Метод render не вызывается, если метод shouldComponentUpdate вернет false.

#компоненты #жизненныйциклкомпонента #документация #примерыкода
componentDidMount

Метод вызывается сразу после монтирования компонента в DOM.

Особенности работы

👉 В методе допустимо вызывать setState(), что сразу же вызовет дополнительный рендер. При этом промежуточное состояние пользователь не увидит. Это может быть полезно для первичного взаимодействия с DOM-элементами, например, для измерения их размера. Однако используйте этот подход с осторожностью.

Типичные случаи использования

👉 Действия с DOM-узлами компонента.
👉 Выполнение сетевых запросов.
👉 Настройка подписок. Не забудьте отписаться от них в методе componentWillUnmount.

#компоненты #жизненныйциклкомпонента #документация #примерыкода
componentWillUnmount

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

Особенности работы

👉 Не следует вызывать setState в методе, так как повторного рендера не будет.

Типичные случаи использования

👉 Отмена подписок.
👉 Отмена сетевых запросов.
👉 Сброс таймеров.

#компоненты #жизненныйциклкомпонента #документация #примерыкода
constructor

Входные параметры

👉 props - пропсы компонента

Особенности работы

👉 Метод не является обязательным, вы можете не определять его, если не используете состояние или не привязываете методы.
👉 При реализации метода не забывайте про вызов super(props) с передачей пропсов.

Типичные случаи использования

👉 Инициализация внутреннего состояния (this.state). Состояние инициализируется простым присваиванием объекта состояния. Не вызывайте здесь метод setState().
👉 Привязка обработчиков событий к экземпляру компонента.
👉 Не следует вызывать побочные эффекты в конструкторе или подписываться на события. Для этого используйте метод componentDidMount.
👉 В конструкторе недоступна DOM-структура компонента. Для работы с ней используйте метод componentDidMount.

#компоненты #жизненныйциклкомпонента #документация #примерыкода
componentDidUpdate

Метод вызывается после обновления компонента. Не вызывается при первом рендере.

Входные параметры

👉 prevProps
👉 prevState
👉 snapshot - результат работы метода getSnapshotBeforeUpdate, если он реалиован

Особенности работы

👉 Вызов setState() внутри метода componentDidUpdate() приведет к бесконечному циклу рендера. Поэтому его необходимо оборачивать в условие или вообще избегать.
👉 Метод componentDidUpdate не вызывается, если метод shouldComponentUpdate вернет false.

Типичные случаи использования

👉 Работа с обновленным DOM.
👉 Сравнение текущих пропсов с предыдущими.
👉 Выполнение сетевых запросов.

#компоненты #жизненныйциклкомпонента #документация #примерыкода
getSnapshotBeforeUpdate

Метод вызывается прямо перед этапом фиксации.

Входные параметры

👉 prevProps
👉 prevState

Типичные случаи использования

👉 Работа с DOM до его обновления (например, сохранение положения прокрутки).
👉 Любое значение, которое вернет этот метод, будет передано в componentDidUpdate.

#компоненты #жизненныйциклкомпонента #документация #примерыкода
static getDerivedStateFromProps

Статический метод класса компонента, вызывается перед вызовом render (и при начальном монтировании, и при обновлениях).

Входные параметры

👉 props
👉 state

Выходные параметры

👉 Объект для обновления состояния.
👉 Или null, если обновлять состояние не требуется.

Особенности работы

👉 Является статическим методом и не имеет доступа к экземпляру компонента.

Типичные случаи использования

👉 Применяется если состояние зависит от изменений в пропсах. Обычно может быть заменен другими методами.

#компоненты #жизненныйциклкомпонента #документация #примерыкода
setState

Мы уже вовсю пользуемся методом экземпляра компонента setState, но до его формального описания в документации добрались только сейчас 🙂

setState принимает изменения состояния и добавляет их в очередь изменений. Эти изменения приводят к обновлению интерфейса (перерендеру) компонента.

Входные параметры

👉 объект нового состояния или функция-коллбэк для обновления состояния, которая принимает аргументы state и props (текущее состояние и пропсы);
👉 callback - коллбэк, который будет вызыван после выполнения setState и повторного рендера компонента. Обычно вместо него используется метод жизненного цикла componentDidUpdate.

setState работает асинхронно, несколько запросов могут объединяться в один. Это может привести к ошибкам, с чем мы уже сталкивались. Если новое состояние зависит от предыдущего состояния, используйте вариант setState с функцией-коллбэком.

Предыдущий пост: setState() - что нужно знать.

#состояние #компоненты #документация
forceUpdate()

Метод экземпляра компонента, который форсированно вызывает метод render(), пропуская shouldComponentUpdate().

Входные параметры

👉 callback

Типичные случаи использования

👉 Необходимость перерендерить компонент без привязки к изменению пропсов или состояния (звучит нелогично, лучше не использовать).

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

Для класса компонента можно определить статическое свойство defaultProps которое позволяет установить дефолтные значения пропсов.

Это должен быть объект, в котором ключами являются имена пропсов.

Эти значения будут использоваться, если соответствующий проп не передан или равен undefined.

#документация #компоненты
displayName

Статическое свойство класса (для классового компонента) или свойство функции (для функционального компонента), которое определяет, как будет отображаться компонент в сообщениях для отладки. По умолчанию используется имя функции/класса, указанное при определении компонента.

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

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

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

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

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

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

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

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

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

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

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

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

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

👉 Стилизация

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

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

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

👉 Прочее

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

Статья (англ.): https://javascript.plainenglish.io/top-10-mistakes-to-avoid-when-using-react-1796711ad2a0

👉 1. Не создавать достаточное количество компонентов
👉 7. Создавать и использовать большие монолитные компоненты

Мы уже говорили, что в React все может быть компонентом, это нормально, и нужно не бояться создавать маленькие компоненты с одной ответственностью. Это намного лучше и удобнее, чем неповоротливые гиганты.

👉 2. Изменять состояние напрямую

Установить state обычным присваиванием можно только в конструкторе классового компонента. Для всего остального существует setState.

👉 3, 9. Передавать пропсы как строки

Если значение пропа заключено в кавычки, он передается как обычная строка. Для чисел, булевых значений и более сложных структур нужно использовать фигурные скобки.

👉 4. Не использовать ключи в списках

Много раз уже проговорили, почему важно устанавливать ключи.

👉 5. Забывать, что setState работает асинхронно

Да, в эту ловушку для новичков мы попались :) Решение тоже разобрали

👉 6. Чрезмерно использовать Redux

До изучения Redux мы еще не добрались, но первые мысли уже можно закладывать в голову. Автор статьи говорит, что если некоторые данные используются в изолированном поддереве компонентов и не расшариваются между многими частями приложения, нет смысла выносить их в Redux.

👉 8. Не использовать структуру папок, принятую в React-комьюнити

Поговорим про это в отдельном посте.

👉 10. Забывать, что имя компонента должно начинаться с заглавной буквы

React признает только компоненты, имя которых начинается с заглавной буквы. Все остальное он обрабатывает как обычные HTML-теги.

#статьи #ошибки #redux #состояние
Файловая структура проекта

Очень важно, чтобы файлы проекта были удобно сгруппированы и не приходилось совершать много движений, чтобы найти нужный.

Структура стандартного React-проекта выглядит так:
(взято отсюда: https://javascript.plainenglish.io/top-10-mistakes-to-avoid-when-using-react-1796711ad2a0)

📂 assets
📂 components - каждый компонент в своей собственной папке
📁 product
📄 product.jsx
📁 navigation
📄 navigation.jsx
📂 containers
📂 hoc
📂 shared
📂 store

Куда девать тесты, стили и прочее вспомогательное будем разбираться по ходу. Например, файлы тестов можно хранить рядом с файлами проверяемых ими компонентов.

Документация React не настаивает на какой-то определенной структуре, говорит, что начинать нужно с чего угодно, а потом понимание само придет.
Статья в документации (рус.): https://ru.reactjs.org/docs/faq-structure.html

#проект #документация
Этапы работы React

Стоит отдельно проговорить важный момент, который может быть неочевиден из предыдущих постов:

React работает в два этапа:

👉 Этап рендеринга (render phase).

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

На этом этапе вызываются constructor, componentWillMount (или UNSAFE_componentWillMount), componentWillReceiveProps(или UNSAFE_componentWillReceiveProps), componentWillUpdate(или UNSAFE_componentWillUpdate), getDerivedStateFromProps, shouldComponentUpdate, render. А также функция setState.

Этап рендеринга занимает очень много времени, каждый из перечисленных методов может быть вызван более одного раза, поэтому очень важно, чтобы они не вызывали побочных эффектов.

👉 Этап фиксации (commit phase)

React обновляет DOM, вызываются методы жизненного цикла componentDidMount и componentDidUpdate.

#документация #компоненты #жизненныйциклкомпонента
**Жизненный цикл компонента

Схема жизненного цикла классового компонента со ссылками на документацию: https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

Монтирование

👉 constructor
👉 static getDerivedStateFromProps
👉 render
👉 componentDidMount

Обновление

👉 static getDerivedStateFromProps
👉 shouldComponentUpdate
👉 render
👉 getSnapshotBeforeUpdate
👉 componentDidUpdate

Размонтирование

👉 componentWillUnmount

Обработка ошибок

👉 static getDerivedStateFromError
👉 componentDidCatch

#документация #компоненты #жизненныйциклкомпонента