Ось готовий урок, створений спеціально за твоїм майстер-промптом. Це не просто лекція, це — перформанс у стилі CS50.
🎓 Урок: Мистецтво зворотного зв'язку: Loading, Error та Empty states
Привіт, друзі! Це CS50 (умовно 😉), і сьогодні ми говоримо про дещо критично важливе. Про те, що відрізняє професійний застосунок від студентської поробки.
1. 🔥 Вступ: Чому мовчання — це не золото
Уявіть ситуацію. Ви заходите в кафе. Підходите до бариста і замовляєте: "Мені, будь ласка, подвійний еспресо".
Бариста дивиться на вас. Мовчки. Він не киває, не починає готувати каву, не каже "Зачекайте хвилинку". Він просто стоїть і дивиться крізь вас. Минає 5 секунд. 10 секунд. Вам стає ніяково. Ви думаєте: "Він мене почув? Може, він завис? Може, кафе зачинене, а я не помітив?"
Врешті-решт ви просто йдете геть.
Риторичне запитання: Скільки разів ви натискали кнопку в додатку, нічого не відбувалося, і ви натискали її ще раз, і ще, і ще?
Ось у чому річ: Користувач не бачить вашого серверу. Він не бачить, як бігають байти по дротах. Якщо інтерфейс мовчить — користувач думає, що він зламався.
Сьогодні ми навчимося робити ваші програми "ввічливими". Ми розберемо три стани, без яких не обходиться жоден сучасний інтерфейс: 1. Loading (Я працюю над цим). 2. Error (Вибач, щось пішло не так). 3. Empty (Я подивився, але там нічого немає).
2. 🧠 Теоретична база: Що там "під капотом"?
Давайте заглянемо всередину. Коли ви відкриваєте Instagram, стрічка не з'являється магічним чином миттєво. Ваша програма (клієнт) робить запит до серверу. Це займає час.
У програмуванні це називається асинхронністю. І поки ми чекаємо, наш інтерфейс перебуває в певному стані (state).
Три кити UX (User Experience):
-
Loading State (Стан завантаження)
- Що це: Індикатор того, що процес іде.
- Мета: Заспокоїти користувача: "Не йди, ми тут, ми працюємо".
- Приклади: Спінер (колесо, що крутиться), прогрес-бар або, що зараз модно, Skeleton (сірі прямокутники, що імітують контент).
-
Error State (Стан помилки)
- Що це: Повідомлення про те, що запит провалився.
- Чому це важливо: Інтернет зникає. Сервери падають. Це нормально. Ненормально — залишати білий екран.
- Логіка: Ми повинні сказати ЩО сталося і ЯК це виправити (кнопка "Спробувати ще").
-
Empty State (Пустий стан)
- Що це: Це успішний запит, який повернув... нічого.
- Приклад: Ви шукаєте "піца з ананасами", а в меню її немає. Результат — 0 товарів.
- Помилка новачків: Показати пустий білий екран. Це збиває з пантелику. Треба написати: "Нічого не знайдено".
💡 Що треба запам'ятати (Інтуїція):
Уявіть змінну status. Вона може бути: 'idle' (очікування), 'loading', 'success', або 'error'. Ваш код — це просто світлофор, який перемикає кольори (екрани) залежно від цього статусу.
3. 🧪 Приклади: Від простого до реального
Давайте напишемо це псевдокодом (схожим на React/JS), щоб зрозуміти логіку.
Приклад 1: "Щасливий шлях" (The Happy Path)
Це те, як пишуть код новачки. Вони вірять, що інтернет ідеальний.
function UserProfile() {
const data = fetchData(); // Магічно отримуємо дані
// Ми просто показуємо дані.
// А що, якщо вони ще не прийшли? Помилка!
return <div>Привіт, {data.name}!</div>;
}
Питання до вас: Що побачить користувач, якщо fetchData займе 3 секунди?
Відповідь: Скоріш за все, програма впаде ("Cannot read property 'name' of undefined") або покаже пусте місце.
Приклад 2: Додаємо Loading та Error
Тепер мислимо як інженери.
function UserProfile() {
// У нас є три змінні стану
const isLoading = ...; // чи вантажиться?
const error = ...; // чи є помилка?
const data = ...; // самі дані
// 1. Спочатку перевіряємо завантаження
if (isLoading) {
return <Spinner />; // 🔄 Крутилка
}
// 2. Потім перевіряємо помилку
if (error) {
return (
<div>
<p>Ой! Не вдалося завантажити профіль.</p>
<button>Спробувати ще раз</button>
</div>
);
}
// 3. Якщо дійшли сюди — у нас є дані!
return <div>Привіт, {data.name}!</div>;
}
Бачите? Це як фільтр. Ми відсіюємо стани один за одним.
Приклад 3: Підступний Empty State
Уявіть, що ми завантажуємо список повідомлень.
Питання: Ми успішно завантажили дані, помилок немає. Але масив повідомлень порожній []. Що покаже код із прикладу 2?
Відповідь: Він покаже просто порожній блок <div></div>. Це погано. Користувач подумає, що зламався інтерфейс.
Виправляємо:
function MessageList() {
if (isLoading) return <SkeletonList />;
if (error) return <ErrorMessage />;
// 🔥 Перевірка на Empty State
if (data.length === 0) {
return (
<div class="empty-state">
<img src="sad-box.png" />
<h3>Повідомлень немає</h3>
<p>Напишіть першим!</p> {/* Заклик до дії! */}
</div>
);
}
// Якщо повідомлення є
return data.map(msg => <Message text={msg} />);
}
4. 🛠 Практична частина
Час забруднити руки кодом! (Можна писати псевдокодом або словами).
Завдання 1: Детектив
У вас є інтернет-магазин. Користувач вводить у пошук "IPhone 15".
Сервер відповідає кодом 200 OK, але список товарів items: [].
Який стан ви маєте показати?
* Loading
* Error
* Empty
* Success (але який саме?)
Завдання 2: "Моргання" Ви зробили лоадер. Але дані завантажилися дуже швидко (за 0.1 сек). Лоадер з'явився на мить і зник. Це виглядає як "глюк" (моргання інтерфейсу). Як би ви вирішили цю проблему логічно?
Завдання 3: Реальний кейс Спроєктуйте Error State для ситуації: "У користувача зник інтернет під час відправки важливого коментаря". * Що ви йому напишете? * Яку кнопку дасте? (Просто "Ок" чи щось краще?) * Чи збережете ви його текст, чи він зникне?
Завдання 4: Bug fix Знайдіть логічну помилку в цьому коді:
if (data) {
return <List items={data} />;
}
if (isLoading) {
return <Spinner />;
}
(Підказка: Що, якщо data вже є з минулого разу, але ми почали оновлювати її і isLoading знову став true?)
5. 💡 Мислення як у розробника
Ось що відрізняє сеньйора від джуніора:
- Джуніор думає про "Happy Path" (коли все працює). Він малює інтерфейс для ідеальних даних.
- Сеньйор починає з "Edge Cases" (крайніх випадків). Він питає: "А що, якщо даних буде нуль? А що, якщо мільйон? А що, якщо сервер впаде?"
Типові помилки:
* Вічний спінер: Коли сталася помилка, але ви забули перемкнути isLoading в false. Користувач буде дивитися на колесо вічно.
* Страшні помилки: Виводити користувачеві технічний текст: Error 500: NullPointerException.
* Як треба: "Наші сервери взяли перерву на каву. Спробуйте пізніше."
* Агресивний Empty State: Писати просто "Даних немає". Це нудно. Використовуйте цей стан, щоб навчити користувача або підштовхнути до дії ("Додайте свій перший товар!").
Професійна порада: Використовуйте Skeletons замість спінерів. Спінер привертає увагу до самого процесу очікування. Скелетон створює ілюзію, що контент вже майже тут. Це психологія!
6. 🧩 Підсумок
Отже, друзі!
Сьогодні ми розібралися, що інтерфейс — це живий організм. Він має спілкуватися з користувачем, навіть коли йому немає чого сказати або коли йому "погано".
Тепер ви вмієте: ✅ Розрізняти Loading, Error та Empty стани. ✅ Розуміти, чому не можна просто показати пустий екран. ✅ Проєктувати логіку відображення даних більш надійно.
Наступного разу ми підемо ще далі. Що, якщо ми покажемо користувачеві результат ще до того, як сервер відповість? Це називається Optimistic UI. І це справжня магія.
А поки що — це був CS50. (І не забудьте обробити помилки у своєму домашньому завданні!) 🚀