От автора: советы по созданию многоразовых и совместно используемых компонентов React.
Проверка типа многоразовых компонентов
Проверка типов необходима для положительного опыта разработчиков и оптимизированного сотрудничества в команде. Это способ сделать код намного более понятным для других, а также для вас самих в будущем.
1. Используйте TypeScript — избегайте prop-types
TypeScript и prop-types в настоящее время являются двумя наиболее популярными способами проверки кода React. Первый проверяет типы во время компиляции, тогда как второй запускается во время выполнения.
Поскольку эти две функции работают по-разному и служат совершенно разным целям, можно утверждать, что они на самом деле не конкурируют друг с другом. Это правда — в теории.
В реальном мире типы TS и prop имеют значительное совпадение в том, как они используются. Вот почему вы редко видели, чтобы они оба использовались в одном проекте. Написание надежного и понятного кода — это замечательно, но это все еще второстепенно по сравнению с фактической доставкой хорошего продукта — и быстрой доставкой.
Поскольку TypeScript предлагает гораздо больше, чем простая проверка типов (лучшие предложения по коду в поддерживаемых IDE и т. д.), и поскольку он все больше становится стандартом для веб-разработки, он кажется правильным выбором для React, особенно для повторно используемых компонентов.
Экспортируйте и импортируйте общие компоненты в виде исходного кода, чтобы насладиться удивительным опытом разработки, предоставляемым TypeScript.
При совместном использовании повторно используемых компонентов с применением таких инструментов, как Bit, компоненты можно экспортировать и импортировать в любое хранилище / кодовую базу в виде исходного кода, что делает все преимущества TypeScript доступными для потребителей и / или сопровождающих специалистов.
Пример: просмотр общих компонентов в bit.dev
Автоматическая генерация документов с использованием react-docgen / bit.dev является еще одним важным преимуществом TS (в этом случае это преимущество общее с prop-types). Например, это –
type RemovableListItemProps = { /** The item's text */ text: string, id: string, /** A callback function for the "X" click event */ removeItem: (id: string) => void } const RemovableListItem : React.FC<RemovableListItemProps> = ({text, id, removeItem} : RemovableListItemProps) => { const [isCompleted, setIsCompleted] = useState(false); return( <li className={styles.listItem}> <span data-iscompleted={isCompleted} className={styles.text} onClick={() => setIsCompleted(!isCompleted)}>{text}</span> <button className={styles.delete} onClick={() => removeItem(id)}>X</button> </li> ) } export default RemovableListItem;
дает это (на странице компонента):
Документация на странице компонента
2. Определите компоненты (не только свойства и события)
Компонент в примере выше написан, как функциональный компонент ( React.FC<T>). Это делается для того, чтобы TS знал и ожидал неявные свойства и типы возврата функционального компонента React (например, свойства ‘children’, возвращаемый тип которого должен быть назначен JSX.Element и т. д.).
Вот короткий пример. При попытке пометить компонент Button, например, так:
import React from 'react'; import './Button.css'; interface IButtonProps { color: 'day' | 'night'; } const Button = ({color} : IButtonProps) => { return ( <button className={color}></button> ) } export default Button;
будет отображаться эта ошибка:
Type '{ children: string; color: "day"; }' is not assignable to type 'IntrinsicAttributes & IButtonProps'. Property 'children' does not exist on type 'IntrinsicAttributes & IButtonProps'.
3. Пишите TS таким способом, который поддерживает автоматическое документирование
При использовании response-docgen/bit.dev для автоматической генерации документов для повторно используемых компонентов тип / интерфейс свойства должен быть определен как универсальный React.FC<T> и (непосредственно) как тип аргументов функции (в противном случае ваши свойства не появятся в сгенерированных документах):
const ExtendedButton : React.FC<IButtonProps> = ({text, type, action} : IButtonProps) => { }
4. Наследуйте типы свойств для нативных HTML-подобных компонентов
Лучший способ определить компонент React, который ведет себя как нативный HTML-элемент — это расширить его тип одним из типов HTML-элементов React:
import React, {ButtonHTMLAttributes} from 'react'; interface IButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { /** The text inside the button */ text: string, /** The type of button, pulled from the Enum ButtonTypes */ type: ButtonTypes, /** The function to execute once the button is clicked */ action: () => void } const ExtendedButton : React.FC<IButtonProps> = ({text, type, action}) => { }
Структурирование каталогов
5. Один каталог для каждого компонента
Поместите все связанные файлы компонента в один и тот же каталог. Это также относится к дочерним компонентам, которые никогда не используются независимо от их родительского компонента (в этом случае поместите дочерний компонент в подкаталог).
Размещение всех файлов в одном каталоге — это еще один способ сделать код более понятным для других разработчиков. Намного легче понять, как различные файлы связаны друг с другом, когда они сгруппированы в одном каталоге. Более того, это способ сделать повторно используемый компонент более «мобильным» и автономным.
Поместить связанные файлы компонента по их типам в разные каталоги не так просто.
6. Используйте псевдонимы
Ссылайтесь на другие компоненты, используя псевдонимы. Наличие пути, подобного указанному выше, затрудняет перемещение файлов компонентов, так как вам необходимо сохранить действительную ссылку. Использование обратных относительных путей связывает компонент с определенной файловой структурой проекта и вынуждает проект-потребитель использовать аналогичную структуру. Webpack, Rollup и Typescript предоставляют методы для использования фиксированных ссылок вместо относительных. Typescript использует сопоставление paths для создания сопоставления со ссылочными компонентами. Rollup использует @rollup/plugin-alias для создания похожих псевдонимов, а Webpack использует для той же цели настройку resolve.alias.
import { } from '@utils'
API
Общее правило заключается в том, чтобы свести охват API компонентов до абсолютно необходимого минимума. Опять же, вы всегда должны стремиться к простоте использования — повторно используемые компоненты не должны иметь кривой обучения.
7. Используйте Enums (вместо нескольких Boolean)
Используйте Enums вместо нескольких логических значений. Взаимозависимости между параметрами затрудняют использование компонентов. Например, сделайте это:
enum Location { TopLeft, TopRight, BottomLeft, BottomRight }interface IProps { location: Location }
вместо этого:
type Location = { isLeft: boolean, isTop: boolean }interface IProps { location: Location }
8. Установите значения по умолчанию
Установка значений по умолчанию — это еще один способ сделать повторно используемые компоненты простыми в использовании. Настройка повторно используемых компонентов должна быть прерогативой ваших потребителей компонентов, а не мандатом.
Ограничьте стили внутри тем
Чтобы обеспечить лучшую предсказуемость поведения компонента (включая его визуальный внешний вид), ограничьте степень свободы, с которой потребители вашего компонента могут переопределять свойства стилей компонента.
Автор: Eden Ella
Источник: https://blog.bitsrc.io
Редакция: Команда webformyself.