58 уроков использования React
Ознакомься с новым проектом
- Просмотри
package.json
, изучи зависимости, скрипты и конфигурацию. - Нарисуй дерево проекта на бумажке/доске или используй React dev tools. Это помогает визуализировать состояние.
Процесс разработки
- Быстрый переход к компоненту или функции: клик с зажатой клавишей
CMD
прямо в JSX (VSCode). - Быстрый переход к родителю:
CMD+SHIFT+F
(глобальный поиск по проекту в VSCode). Искать<Название_компонента
. - Быстрый просмотр списка родителей: React dev tools.
- Создавай чеклист возможных состояний каждого компонента (ошибка, нет данных и т. д. — полный список).
- Для дебаггинга используй
debugger
. Также полезен методconsole.assert
. - Работай с фиктивными данными и фиктивным API (json-server, json-graphql-server).
- Используй одни и те же фиктивные данные для Storybook, тестов и фиктивного API.
- Передавай в функцию объект и используй деструктурирование для получения именованных параметров. Это читается гораздо проще. Деструктурировать можно прямо в сигнатуре функции, это позволяет сразу же документировать ожидаемые параметры.
- Storybook driven development — создавай и тестируй каждый компонент изолированно. Каждое состояние документа — это отдельная история. Затем используй Percy или Chromatic для снэпшотов.
- Отступы
- Адаптивный дизайн
JSX
- Можно использовать только выражения, которые что-то возвращают. Для сложной логики есть несколько вариантов:
- Ранний
return
(удобно для лоадеров и ошибок) - Выделение логики рендера в отдельную функцию, где можно использовать все возможности Javascript (
if
/else
/switch
)
- Ранний
Производительность
- Делай то, что удобно. Чаще всего это достаточно хорошо работает. Инлайн-функции? Отлично. Беспокоишься о рендере? Не беспокойся. Беспокоишься о производительности контекста? Может быть, ты неправильно используешь контекст (он должен меняться довольно редко). В любом случае тестируй, но не сходи с ума. Добиваясь идеальной производительности, ты потеряешь удобство.
- Помни, что рендер компонента — не равно изменению DOM-дерева. React работает с виртуальным DOM. Процесс применения изменений выглядит так: рендер (render) -> согласование (reconcile) -> применение (commit). Если DOM не изменяется, то и проблем с производительностью не будет, поэтому перестань волноваться о перерендерах. React достаточно умный, чтобы изменять только то, что требует изменения.
- Не используй везде, где можно,
useMemo
,shouldComponentUpdate
,PureComponent
. Только если это действительно нужно. У них есть накладные расходы, так как совершаются дополнительные действия. Если бы они были быстрыми, то использовались бы по умолчанию!
Управление состоянием
- Держи состояние так низко, как это только возможно. При необходимости поднимай.
- Избегай хранить состояние, которое может быть извлечено из другого состояния или пропсов. Вычисляй на лету. Ссылайся на объекты по идентификатору вместо того, чтобы дублировать их.
- Используй
_myVar
конвенцию для разрешения конфликтов именования состояния. - Не синхронизируй состояния, а извлекай. Например, получай полное имя (
full
name) путем объединения имени (firstName
) и фамилии (lastName
) прямо в методе render. - Состояния, которые изменяются вместе, должны храниться вместе. В этом помогают редьюсеры. Группируй, используй useState. Рассмотрим движки состояний — они описывают валидные состояния, что делает невалидные состояния невозможными (например, новый клиент, у которого уже есть 5 прошлых покупок, или админ без прав) Если разделить состояния, они могут рассинхронизироваться.
- Возможно тебе не нужен Redux. Подъем состояния отлично масштабируется и легок для понимания. Пробрасывание пропсов не так страшно, как его малюют. Просто сохраняй названия пропсов, используй спред-оператор, передавай детей целиком, используй мемоизацию. Контекст и useReducer могут справиться практически с любой задачей.
- Контекст полезен не только для хранения глобальных данных. Его можно использовать для композиции компонентов. Он также может быть полезен для увеличения производительности.
- Вызывай
setLoading(false)
в блокеfinally
.
Пропсы
- Сделай все пропсы обязательными.
- Деструктурируй пропсы в сигнатуре функции, чтобы уменьшить количество кода. Это также полезно для обработчиков событий. Но что насчет пропсов, в имени которых есть дефис типа
aria-label
. Просто используй синтаксис...otherProps
. - Сделай пропсы максимально специфичными.
- Используй стандартизированное наименование.
onX
для пропсов-обработчиков событий,handleX
— для функций. - Храни propTypes в одном месте.
- Документируй propTypes с помощью JSDoc-комментариев, они будут выводиться в автокомплите редактора. Можно даже использовать markdown.
- Чтобы уменьшить проблему пробрасывания пропсов, используй спред-оператор или передавай дочерние элементы.
- Само существование пропа предполагает, что он равен
true
. Поэтому достаточно написать<Input required />
. - Держись ближе к нативному API. В обработчики передавай событие целиком, а не только значение инпута. Тогда ты сможешь использовать единый обработчик изменений. Придерживайся нативных имен (
onBlur
,onChange
). Стремись к максимальной гибкости и минимальной кривой обучения.
Стили
- Сочетай разные подходы:
- Инлайновые стили для динамически изменяющихся свойств.
- Пространства имен (CSS-модули).
- Sass для глобальных стилей.
- Используй классы, чтобы применять несколько стилей сразу.
- Используй flexbox или CSS Grid вместо
float
. - Создавай абстракции для брейкпоинтов (например, используй bootstrap).
Переиспользование компонентов
- 3 ключевых правила для простого переиспользования.
- Подумай о том, чтобы выделить на это отдельного человека/команду. Зачем это нужно? Скорость работы, быстрее и проще принимать решения, меньше бандлы. Слаженность в интерфейсе ведет к хорошему пользовательскому опыту. Меньше кода — меньше багов.
- Ищи повторящийся код — его можно повторно использовать. Любое переиспользование — это улучшение производительности.
- Следуй принципу DRY, объединяй возможности хуков, контекста и переиспользуемые компоненты, чтобы инкапсулировать всю бизнес-логику приложения.
- Принимай и простые строки и элементы. Используй React.isValidElement, чтобы определить, что ты получаешь.
- Создай проп
as
для обозначения элементов высокого уровня. - Cоздай переиспользуемый AppLayout, используя слоты.
- Помести алерты в одно место в AppLayout и предоставь функцию для их отображения через контекст.
- Генерируй документацию через react-docgen.
- Подумай о создании отдельных компонентов для мобильной и десктопной версии (если он сильно различаются). Используй lazy load для загрузки нужного размера.
Тестирование
- RTL лучше Enzyme. Чем проще API, тем лучше. Поощряет a11y. Проще отлаживать. Можно использовать те же запросы для Cypress.
- JSDOM не рендерит, поэтому не может тестировать адаптивный дизайн. Используй Cypress для теста адаптивного поведения.
- Избегай снэпшот-тестов Jest. Они хрупкие, тестирую детали реализации, плохо называются, всегда падают при изменении единственной строки и их трудно поднять. Вместо этого используй Percy или Chromatic для визуальных тестов.
- Используй шаблон выбора сценариев для запуска приложения с различными данными. Автоматизировать эти тесты можно с помощью Cypress/Selenium.
- При использовании Cypress Cy-селекторы совпадают с RTL-селекторам — не нужно менять код для поддержки тестов Cypress.
- Cypress driven development — TDD для интеграционных тестов. Используй Cypress, чтобы перейти к месту, которое нужно проверить. Используй
cy.only
чтобы запустить один тест. В первый раз он должен упасть, это пройдет.
Среда разработки
- Кастомизируй create-react-app (CRA)
- Используй react-app-rewired для настройки конфигурации без ejecting.
- Кастомизируй правила линтинга.
- Добавь webpack-bundle-analyzer, узнай, что в твоем бандле.
- Форкни CRA или хотя бы react scripts. Создай фреймворк для компании, который генерирует проект с единственной зависимостью — этим форком, включающим компоненты, правила линтинга, конфиги и т. д.
- Используй Prettier.
- Положись на ESLint. Используй как учебное пособие. Object shorthand. No var. Запрет некоторых импортов (jquery, lodash, moment). Строгое равенство. Добавьте плагины типа jsx-a11y/recommended.
- Используй строгие propTypes (или TS).
- Используй .vsextensions.
- Разделяй клиент и сервер. Если используешь React на сервере, используй Storybook для изолированной разработки компонентов.