React.js: делаем код чище с централизованными PropTypes

Как сократить самоповторы и сделать код чище, синхронизировать серверный код и централизировать PropTypes при использовании React.js?

PropTypes

Существует 3 популярных подхода для работы с типами в React: PropType, TypeScript и Flow.

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

  • Компонент принимает объект? Объявите форму объекта.
  • Prop принимает определенный список значений? Используйте oneOf.
  • Массив должен содержать числа? Используйте arrayOf.
  • Можно объявлять собственные типы.

Пример PropType:

UserDetails.propTypes = {
 user: PropTypes.shape({
   id: PropTypes.number.isRequired,
   firstName: PropTypes.string.isRequired,
   lastName: PropTypes.string.isRequired,
   role: PropTypes.oneOf(['user','admin'])
};

В существующих приложениях с большими объектами, это быстро приведет к большому количеству кода. Это проблема, так как в Реакте часто нужно передавать один и тот же объект множеству компонентов. Повторение этого процесса во множестве компонентов нарушает принцип DRY (Don’t Repeat Yourself). Самоповторы приводят к проблемам с поддержкой.

Как централизовать PropTypes

Централизовать типы можно в ‘/types/index.js’.

// types/index.js
import { shape, number, string, oneOf } from 'prop-types';

export const userType = shape({
  id: number,
  firstName: string.isRequired,
  lastName: string.isRequired,
  company: string,
  role: oneOf(['user', 'author']),
  address: shape({
    id: number.isRequired,
    street: string.isRequired,
    street2: string,
    city: string.isRequired,
    state: string.isRequired,
    postal: number.isRequired
  });
});

Для сокращения объявлений на второй строке используются именованные импорты.

И вот как можно использовать уже объявленные типы:

import React from 'react';
import {userType} from './types';

function User({ user }) {
  return (
    <div>
      <h1>{user.firstName} {user.lastName}</h1>
    </div>
  )
}

User.propTypes = {
  user: userType.isRequired
};

export default User;

Использование именованных импортов дает возможность отсылаться к экспортированному PropType, объявленному на второй строке. Он используется на строке 13.

Преимущества этого подхода:

  • Централизованные типы существенно упрощают их объявление в компоненте. Строка 13 отсылает к централизованному PropType, код легко читается.
  • Централизованные типы просто объявляют форму, их можно отмечать как обязательные.
  • Нет необходимости в копипасте. Если форма объекта меняется позже, внести изменения нужно только в одном месте.

Попробуйте написать код, который будет генерировать ваши собственные типы на сервере. Для примера, если API написано на строго типизированном языке, вроде C# или Java, попробуйте генерировать объявления PropType как часть процесса сборки серверного API, читая форму серверных классов. Таким образом, не придется волноваться о сохранении PropType на клиенте и серверный код будет синхронизирован.

Резюмируя

  1. Объявление типов происходит настолько явно, насколько это возможно, поиск ошибки не занимает много времени.
  2. Централизация типов помогает избегать самоповторов.
  3. При работе со строго типизированными языками на сервере рассмотрите возможность генерации типов, читая серверный код. Это обеспечит совпадение типов на сервере и клиенте.

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ