Опишите Product, отделите асинхронную загрузку от карточки и явно отрисуйте loading, error и пустой список.
Практическое задание: реализовать магазин товаров на React/TypeScript — отрендерить список товаров с карточками, содержащими изображение, название, описание и стоимость. Данные загружаются через имитацию сервера.
Опишите Product, отделите асинхронную загрузку от карточки и явно отрисуйте loading, error и пустой список.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Опишите Product, отделите асинхронную загрузку от карточки и явно отрисуйте loading, error и пустой список.
Минимальный каркас с внедрённой имитацией API:
import { useEffect, useState } from 'react';
type Product = { id: string; image: string; title: string; description: string; price: number };
export function Shop({ load }: { load: () => Promise<Product[]> }) {
const [items, setItems] = useState<Product[] | null>(null);
const [error, setError] = useState(false);
useEffect(() => {
let active = true;
setItems(null); setError(false);
Promise.resolve().then(load).then(
data => { if (active) setItems(data); },
() => { if (active) setError(true); }
);
return () => { active = false; };
}, [load]);
if (error) return <p role="alert">Не удалось загрузить товары</p>;
if (items === null) return <p>Загрузка…</p>;
if (!items.length) return <p>Товаров нет</p>;
return <ul>{items.map(p => <li key={p.id}>
<img src={p.image} alt={p.title} />
<h2>{p.title}</h2><p>{p.description}</p><p>{p.price}</p>
</li>)}</ul>;
}
Передавайте стабильную load, определённую вне render или мемоизированную по реальным зависимостям. Это условный контракт: валюту, единицы цены и формат mock-сервера нужно согласовать отдельно.