React.js: делаем код чище с централизованными PropTypes
Как сократить самоповторы и сделать код чище, синхронизировать серверный код и централизировать PropTypes при использовании React.js?
Существует 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 на клиенте и серверный код будет синхронизирован.
Резюмируя
- Объявление типов происходит настолько явно, насколько это возможно, поиск ошибки не занимает много времени.
- Централизация типов помогает избегать самоповторов.
- При работе со строго типизированными языками на сервере рассмотрите возможность генерации типов, читая серверный код. Это обеспечит совпадение типов на сервере и клиенте.