Ось урок, побудований за принципами CS50 та Девіда Малана.
🎓 Тема уроку: Робота з даними між компонентами (Data Flow)
Стек: Загальні концепції (на прикладі React-подібного синтаксису, оскільки це стандарт індустрії).
1. 🔥 Вступ: Проблема та мотивація
Уявіть, що ви будуєте будинок з LEGO. У вас є окремі цеглинки: вікно, двері, дах. У програмуванні ми називаємо їх компонентами.
Але ось проблема: у реальному додатку ці "цеглинки" не просто стоять на місці. Вони мають бути живими.
Уявіть, що ви робите Інстаграм. У вас є компонент Avatar (аватарка) і компонент Profile (профіль).
Як компонент Avatar дізнається, чию саме фотографію показувати? Вашу? Мою? Ілона Маска?
Якщо кожен компонент — це ізольований острів, як вони спілкуються?
Риторичне питання: Якби ви були начальником великої кухні, як би ви передали кухарю замовлення від клієнта? Ви б кричали через весь зал? Чи передали б чіткий папірець із замовленням?
Без розуміння того, як дані "течуть" між компонентами, ваш додаток буде просто набором красивих, але мертвих картинок. Сьогодні ми навчимо ці картинки "розмовляти" одна з одною.
Аналогія: Водоспад. 🌊 Уявіть, що дані — це вода. У більшості сучасних систем (React, Vue, Angular) вода тече тільки зверху вниз. Ви (батьківський компонент) наливаєте воду (дані) у склянки, що стоять нижче (дочірні компоненти). Але вода не може текти вгору сама по собі. Запам'ятайте цей образ.
2. 🧠 Теоретична база (Як це працює під капотом)
Давайте розберемо механіку без зайвих слів. Є два головних гравці:
1. Props (Властивості / Пропси)
Це дані, які батько передає дитині.
* Як це працює: Це як аргументи функції. Коли ви викликаєте функцію sum(a, b), ви передаєте їй a і b. Компонент — це та сама функція.
* Головне правило: Props — це read-only (тільки для читання). Дитина отримує кишенькові гроші від батьків, але вона не може змінити суму зарплати батьків. Вона може тільки використати те, що їй дали.
2. Events / Callbacks (Події)
Якщо вода тече вниз, як дитина може щось сказати батькам (наприклад: "Я хочу їсти")? * Як це працює: Батько передає дитині не тільки дані, а й "пульт керування" (функцію). * Аналогія: Батько дає дитині рацію і каже: "Якщо буде біда, натисни цю кнопку". Дитина натискає кнопку (викликає функцію), і сигнал йде вгору до батька.
🧩 "Підняття стану" (Lifting State Up)
Що робити, якщо два брати (два сусідні компоненти) хочуть поговорити? Наприклад, один компонент — це "Кошик товарів", а інший — "Сума до сплати". Вони не можуть говорити напряму. Рішення: Вони говорять через спільного батька. Один каже батькові: "Я додав товар", батько оновлює дані і передає нову суму іншому брату.
3. 🧪 Приклади (Код speaks louder than words)
Ми використовуватимемо спрощений синтаксис (JSX), щоб зрозуміти суть.
Приклад 1: Проста передача (Props)
У нас є компонент Welcome. Він дурненький, він вміє тільки вітатися. Але кого вітати — вирішує App (головний компонент).
// Дочірній компонент (Child)
function Welcome(props) {
// props.name - це те, що прийшло зверху
return <h1>Привіт, {props.name}!</h1>;
}
// Батьківський компонент (Parent)
function App() {
return (
<div>
<Welcome name="Олексій" />
<Welcome name="Марія" />
</div>
);
}
Питання до вас: Що ми побачимо на екрані? Правильно: Два заголовки. Один "Привіт, Олексій!", другий "Привіт, Марія!". Один і той самий код (шаблон) використав різні дані.
Приклад 2: Інтерактив (Зворотний зв'язок)
А тепер складніше. У нас є кнопка. Батько хоче знати, коли на неї натиснуть.
// Child
function MagicButton(props) {
return (
// Коли клікають, ми викликаємо функцію, яку нам дав батько
<button onClick={props.onMagicClick}>
Натисни мене!
</button>
);
}
// Parent
function App() {
// Це функція батька
function handleAlert() {
alert("Магія відбулася! ✨");
}
return (
<div>
{/* Передаємо функцію вниз як пропс */}
<MagicButton onMagicClick={handleAlert} />
</div>
);
}
Чому це важливо? Кнопка (MagicButton) не знає, що станеться при кліку. Вона просто повідомляє: "Мене клікнули!". А батько (App) вирішує, що робити (показати алерт, завантажити дані, видалити файл). Це називається розділенням відповідальності.
4. 🛠 Практична частина
Прийшов час бруднити руки кодом. Виконайте ці завдання (можна подумки, на папері або в редакторі коду):
🔹 Завдання 1: "Візитка"
Створіть компонент UserCard, який приймає три пропси: name, job, age.
У батьківському компоненті виведіть три такі картки для різних людей.
🔹 Завдання 2: "Зламайте систему"
Спробуйте всередині компонента UserCard написати props.age = 100.
Що станеться? (Якщо редактор розумний, він видасть помилку. Якщо ні — в браузері нічого не зміниться або буде помилка). Поясніть чому.
🔹 Завдання 3: "Лічильник лайків" (Міні-кейс)
Це класика.
1. У батьківському компоненті є змінна likes (число).
2. Є дочірній компонент LikeButton.
3. Коли тиснеш на LikeButton, число у батька має збільшуватися на +1.
Підказка: Вам треба передати вниз і саме число (щоб показати його), і функцію для його зміни.
🔹 Питання "А що, якщо...": У вас є список товарів. Кожен товар — це окремий компонент. У кожного товара є кнопка "Видалити". Де повинна жити функція видалення: всередині товару чи у списку товарів?
5. 💡 Мислення як у розробника
Як думає досвідчений інженер (Senior), коли проектує компоненти?
-
"Single Source of Truth" (Єдине джерело істини). Новачки часто дублюють дані. Вони тримають "ім'я користувача" і в шапці сайту, і в профілі окремо. Профі думає: "Де лежить оригінал даних? Тільки в одному місці зверху. Всі інші лише отримують посилання на нього".
-
Dumb vs Smart Components (Розумні та Дурні компоненти).
- Дурні (Презентаційні): Тільки показують те, що їм дали (як наш
Welcome). Вони легкі, їх просто перевикористовувати. - Розумні (Контейнери): Керують даними, роблять запити на сервер, передають дані вниз.
- Порада: Намагайтеся робити компоненти максимально "дурними". Нехай логіка живе якомога вище.
- Дурні (Презентаційні): Тільки показують те, що їм дали (як наш
-
Prop Drilling (Проблема свердління). Новачок передає пропс через 10 компонентів вниз, щоб він дійшов до потрібного. Профі думає: "Якщо мені треба передавати дані через 5 посередників, можливо, моя архітектура погана, або час використати глобальний стейт (Context/Redux)". Але про це — в наступних уроках.
6. 🧩 Підсумок
Отже, що ми сьогодні розібрали?
- Дані течуть вниз (як водоспад) через
Props. - Події піднімаються вгору (як ракета) через функції-колбеки.
- Компоненти не повинні змінювати дані, які їм дали (Immutable props).
Тепер ви вмієте: Створювати не просто статичні сторінки, а динамічні системи, де батьківський елемент керує цілою армією маленьких компонентів. Ви навчилися делегувати!
🔮 Тизер наступного уроку: А що робити, якщо у нас 50 рівнів вкладеності? Або якщо дані потрібні двом компонентам, які знаходяться в абсолютно різних кутках програми і не мають спільного батька поруч? Невже передавати пропси через весь додаток? Ні. На наступному уроці ми поговоримо про "Телепорт даних" — Context API та Global State Management.
Це був CS50... тобто, ваш урок з React. Побачимось! 👋