Компоненты: функция, которая возвращает экран
Компонент как функция с входами и одним выходом, props как входы только для чтения и почему собирать большое из маленького лучше, чем копировать и вставлять.
Откройте любое настоящее приложение и посчитайте мелкие повторяющиеся кусочки: бейдж, цена, строка списка, карточка товара. Каждый из них — компонент. Написать его — не столько новый навык, сколько старый навык в другой одежде.
В разделе про языки функция была именованной коробкой: значения входят, одно значение выходит, а имя — это то, как её вызывают. Компонент — ровно такая коробка с одной разницей: на выходе получается кусок интерфейса.
function totalPrice(price, count) {
return price * count;
}
totalPrice(2.50, 4);
function Badge({ label }) {
return <span className="badge">{label}</span>;
}
const view = <Badge label="New" />;Одна и та же форма дважды: числа на входе и число на выходе, props на входе и элементы на выходе.В этом весь фокус. Компонент — это именованный кусок интерфейса. Вы даёте ему имя, говорите, что ему нужно, и дальше остальная программа может попросить бейдж или строку с ценой, не зная, как нарисовано то или другое.
Вот каталог: три товара, одна форма карточки. Написана один раз, использована трижды.
function ProductCard({ title, price, inStock }) {
return (
<article>
<h2>{title}</h2>
<p>{price}</p>
{inStock ? <button>Add</button> : <p>Sold out</p>}
</article>
);
}
function Catalogue() {
return (
<section>
<ProductCard title="Bread" price="2.50" inStock={true} />
<ProductCard title="Tea" price="3.20" inStock={false} />
<ProductCard title="Apples" price="1.80" inStock={true} />
</section>
);
}Одна карточка, описанная один раз, использованная трижды с разными входами.Входы записываются как атрибуты и приходят вместе, одним объектом, который называется props. В этом примере карточка получает title, price и inStock и не интересуется, откуда они взялись.
function Price({ amount }) {
amount = amount + 1;
return <p>{amount}</p>;
}
function Price({ amount }) {
const [shown, setShown] = useState(amount);
return <p>{shown}</p>;
}Вторая версия лучше не потому, что длиннее. Она лучше потому, что число теперь принадлежит компоненту, который его меняет.Честная альтернатива компонентам — копирование и вставка, и для двух карточек это нормально. Счёт приходит позже. Дизайнер просит скруглить углы у каждой карточки: теперь вы правите двенадцать файлов. Правило расчёта цены меняется, теперь в неё входит налог: вы исправляете девять файлов, три пропускаете, и каталог показывает две разные цены на один и тот же товар. Компонент превращает каждое такое изменение в одну правку в одном месте, потому что есть только одно место, которое знает, как выглядит карточка.
Практика
Компонент карточки товара получает title, price и inStock от каталога вокруг него. Ему нужно показать, распродан товар или нет. Что из этого компонент может перезаписать?
Подсказки
- Одно из этого — данные, пришедшие извне компонента. Всё, что компонент получает, попадает в эту категорию.
- Prop не хранится внутри компонента. Если что-то внутри меняется само, оно не могло прийти как prop.
Каталог рисует карточку товара для каждого полученного элемента. Расставьте путь от данных к пикселям по порядку.
- 1Карточка возвращает описание нужных ей элементов
- 2Элементы рисуются внутри страницы
- 3Функция карточки выполняется и читает эти входы
- 4Родитель создаёт карточку и передаёт ей входы
Подсказки
- Начните на шаг выше самой карточки и закончите тем, что браузер может нарисовать.
- Внутри карточки путь идёт от собранных входов к возвращённым деревьям.
Сопоставьте каждую часть компонента с той частью функции, которую она играет.
Подсказки
- Сопоставьте каждый кусок интерфейса с той ролью, которую он играет в функции.
- Входы — это скобки, имя — то, как компонент вызывают снаружи, правило — то, что происходит внутри.