Оригинал: 55 Lessons From 5 Years in React, автор Cory House

Разработчик делится своим пятилетним опытом использования React: читаем и учимся на чужих ошибках.

Ознакомься с новым проектом

  1. Просмотри package.json, изучи зависимости, скрипты и конфигурацию.
  2. Нарисуй дерево проекта на бумажке/доске или используй React dev tools. Это помогает визуализировать состояние.

Процесс разработки

  1. Быстрый переход к компоненту или функции: клик с зажатой клавишей CMD прямо в JSX (VSCode).
  2. Быстрый переход к родителю: CMD+SHIFT+F (глобальный поиск по проекту в VSCode). Искать <Название_компонента.
  3. Быстрый просмотр списка родителей: React dev tools.
  4. Создавай чеклист возможных состояний каждого компонента (ошибка, нет данных и т. д. — полный список).
  5. Для дебаггинга используй debugger. Также полезен метод console.assert.
  6. Работай с фиктивными данными и фиктивным API (json-server, json-graphql-server).
  7. Используй одни и те же фиктивные данные для Storybook, тестов и фиктивного API.
  8. Передавай в функцию объект и используй деструктурирование для получения именованных параметров. Это читается гораздо проще. Деструктурировать можно прямо в сигнатуре функции, это позволяет сразу же документировать ожидаемые параметры.
  9. Storybook driven development — создавай и тестируй каждый компонент изолированно. Каждое состояние документа — это отдельная история. Затем используй Percy или Chromatic для снэпшотов.
    • Отступы
    • Адаптивный дизайн

JSX

  1. Можно использовать только выражения, которые что-то возвращают. Для сложной логики есть несколько вариантов:
    • Ранний return (удобно для лоадеров и ошибок)
    • Выделение логики рендера в отдельную функцию, где можно использовать все возможности Javascript (if/else/switch)

Производительность

  1. Делай то, что удобно. Чаще всего это достаточно хорошо работает. Инлайн-функции? Отлично. Беспокоишься о рендере? Не беспокойся. Беспокоишься о производительности контекста? Может быть, ты неправильно используешь контекст (он должен меняться довольно редко). В любом случае тестируй, но не сходи с ума. Добиваясь идеальной производительности, ты потеряешь удобство.
  2. Помни, что рендер компонента — не равно изменению DOM-дерева. React работает с виртуальным DOM. Процесс применения изменений выглядит так: рендер (render) -> согласование (reconcile) -> применение (commit). Если DOM не изменяется, то и проблем с производительностью не будет, поэтому перестань волноваться о перерендерах. React достаточно умный, чтобы изменять только то, что требует изменения.
  3. Не используй везде, где можно, useMemo, shouldComponentUpdate, PureComponent. Только если это действительно нужно. У них есть накладные расходы, так как совершаются дополнительные действия. Если бы они были быстрыми, то использовались бы по умолчанию!

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

  1. Держи состояние так низко, как это только возможно. При необходимости поднимай.
  2. Избегай хранить состояние, которое может быть извлечено из другого состояния или пропсов. Вычисляй на лету. Ссылайся на объекты по идентификатору вместо того, чтобы дублировать их.
  3. Используй _myVar конвенцию для разрешения конфликтов именования состояния.
  4. Не синхронизируй состояния, а извлекай. Например, получай полное имя (full name) путем объединения имени (firstName) и фамилии (lastName) прямо в методе render.
  5. Состояния, которые изменяются вместе, должны храниться вместе. В этом помогают редьюсеры. Группируй, используй useState. Рассмотрим движки состояний — они описывают валидные состояния, что делает невалидные состояния невозможными (например, новый клиент, у которого уже есть 5 прошлых покупок, или админ без прав) Если разделить состояния, они могут рассинхронизироваться.
  6. Возможно тебе не нужен Redux. Подъем состояния отлично масштабируется и легок для понимания. Пробрасывание пропсов не так страшно, как его малюют. Просто сохраняй названия пропсов, используй спред-оператор, передавай детей целиком, используй мемоизацию. Контекст и useReducer могут справиться практически с любой задачей.
  7. Контекст полезен не только для хранения глобальных данных. Его можно использовать для композиции компонентов. Он также может быть полезен для увеличения производительности.
  8. Вызывай setLoading(false) в блоке finally.

Пропсы

  1. Сделай все пропсы обязательными.
  2. Деструктурируй пропсы в сигнатуре функции, чтобы уменьшить количество кода. Это также полезно для обработчиков событий. Но что насчет пропсов, в имени которых есть дефис типа aria-label. Просто используй синтаксис ...otherProps.
  3. Сделай пропсы максимально специфичными.
  4. Используй стандартизированное наименование. onX для пропсов-обработчиков событий, handleX — для функций.
  5. Храни propTypes в одном месте.
  6. Документируй propTypes с помощью JSDoc-комментариев, они будут выводиться в автокомплите редактора. Можно даже использовать markdown.
  7. Чтобы уменьшить проблему пробрасывания пропсов, используй спред-оператор или передавай дочерние элементы.
  8. Само существование пропа предполагает, что он равен true. Поэтому достаточно написать <Input required />.
  9. Держись ближе к нативному API. В обработчики передавай событие целиком, а не только значение инпута. Тогда ты сможешь использовать единый обработчик изменений. Придерживайся нативных имен (onBlur, onChange). Стремись к максимальной гибкости и минимальной кривой обучения.

Стили

  1. Сочетай разные подходы:
    • Инлайновые стили для динамически изменяющихся свойств.
    • Пространства имен (CSS-модули).
    • Sass для глобальных стилей.
  2. Используй классы, чтобы применять несколько стилей сразу.
  3. Используй flexbox или CSS Grid вместо float.
  4. Создавай абстракции для брейкпоинтов (например, используй bootstrap).

Переиспользование компонентов

  1. 3 ключевых правила для простого переиспользования.
  2. Подумай о том, чтобы выделить на это отдельного человека/команду. Зачем это нужно? Скорость работы, быстрее и проще принимать решения, меньше бандлы. Слаженность в интерфейсе ведет к хорошему пользовательскому опыту. Меньше кода — меньше багов.
  3. Ищи повторящийся код — его можно повторно использовать. Любое переиспользование — это улучшение производительности.
  4. Следуй принципу DRY, объединяй возможности хуков, контекста и переиспользуемые компоненты, чтобы инкапсулировать всю бизнес-логику приложения.
  5. Принимай и простые строки и элементы. Используй React.isValidElement, чтобы определить, что ты получаешь.
  6. Создай проп as для обозначения элементов высокого уровня.
  7. Cоздай переиспользуемый AppLayout, используя слоты.
  8. Помести алерты в одно место в AppLayout и предоставь функцию для их отображения через контекст.
  9. Генерируй документацию через react-docgen.
  10. Подумай о создании отдельных компонентов для мобильной и десктопной версии (если он сильно различаются). Используй lazy load для загрузки нужного размера.

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

  1. RTL лучше Enzyme. Чем проще API, тем лучше. Поощряет a11y. Проще отлаживать. Можно использовать те же запросы для Cypress.
  2. JSDOM не рендерит, поэтому не может тестировать адаптивный дизайн. Используй Cypress для теста адаптивного поведения.
  3. Избегай снэпшот-тестов Jest. Они хрупкие, тестирую детали реализации, плохо называются, всегда падают при изменении единственной строки и их трудно поднять. Вместо этого используй Percy или Chromatic для визуальных тестов.
  4. Используй шаблон выбора сценариев для запуска приложения с различными данными. Автоматизировать эти тесты можно с помощью Cypress/Selenium.
  5. При использовании Cypress Cy-селекторы совпадают с RTL-селекторам — не нужно менять код для поддержки тестов Cypress.
  6. Cypress driven development — TDD для интеграционных тестов. Используй Cypress, чтобы перейти к месту, которое нужно проверить. Используй cy.only чтобы запустить один тест. В первый раз он должен упасть, это пройдет.

Среда разработки

  1. Кастомизируй create-react-app (CRA)
    • Используй react-app-rewired для настройки конфигурации без ejecting.
    • Кастомизируй правила линтинга.
    • Добавь webpack-bundle-analyzer, узнай, что в твоем бандле.
    • Форкни CRA или хотя бы react scripts. Создай фреймворк для компании, который генерирует проект с единственной зависимостью — этим форком, включающим компоненты, правила линтинга, конфиги и т. д.
  2. Используй Prettier.
  3. Положись на ESLint. Используй как учебное пособие. Object shorthand. No var. Запрет некоторых импортов (jquery, lodash, moment). Строгое равенство. Добавьте плагины типа jsx-a11y/recommended.
  4. Используй строгие propTypes (или TS).
  5. Используй .vsextensions.
  6. Разделяй клиент и сервер. Если используешь React на сервере, используй Storybook для изолированной разработки компонентов.

Полезные материалы

2 комментария

  • jager
    jager
    31/12/2019, 13:36
    Как это сочетается? > Сделай все пропсы обязательными и > Само существование пропа предполагает, что он равен true. Поэтому достаточно написать . как быть, если проп обязательный, но нам нужен false?
    • Furry_web
      Furry_web
      2/01/2020, 00:17
      Эти пункты про разные вещи. Обязательными - в смысле, чтобы проп обязательно был в наличии. Неважно с каким значением. Если это булев тип, то может быть как true, так и false. Второй пункт касается только краткого синтаксиса. Если передаешь true, необязательно писать <Input required="true" />. Можно написать просто <Input required />. А если надо передать false, то придется писать полностью <Input required="false" />

Оставить комментарий

*Доступные HTML-теги: a, abbr, blockquote, code, pre, del, i, em, strong, b, strike
*Не будет опубликован