55 уроков после 5 лет использования React

Разработчик делится своим пятилетним опытом использования 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 для изолированной разработки компонентов.

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *