Модуль 17

Робота з даними між компонентами

Ось урок, побудований за принципами 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), коли проектує компоненти?

  1. "Single Source of Truth" (Єдине джерело істини). Новачки часто дублюють дані. Вони тримають "ім'я користувача" і в шапці сайту, і в профілі окремо. Профі думає: "Де лежить оригінал даних? Тільки в одному місці зверху. Всі інші лише отримують посилання на нього".

  2. Dumb vs Smart Components (Розумні та Дурні компоненти).

    • Дурні (Презентаційні): Тільки показують те, що їм дали (як наш Welcome). Вони легкі, їх просто перевикористовувати.
    • Розумні (Контейнери): Керують даними, роблять запити на сервер, передають дані вниз.
    • Порада: Намагайтеся робити компоненти максимально "дурними". Нехай логіка живе якомога вище.
  3. Prop Drilling (Проблема свердління). Новачок передає пропс через 10 компонентів вниз, щоб він дійшов до потрібного. Профі думає: "Якщо мені треба передавати дані через 5 посередників, можливо, моя архітектура погана, або час використати глобальний стейт (Context/Redux)". Але про це — в наступних уроках.


6. 🧩 Підсумок

Отже, що ми сьогодні розібрали?

  1. Дані течуть вниз (як водоспад) через Props.
  2. Події піднімаються вгору (як ракета) через функції-колбеки.
  3. Компоненти не повинні змінювати дані, які їм дали (Immutable props).

Тепер ви вмієте: Створювати не просто статичні сторінки, а динамічні системи, де батьківський елемент керує цілою армією маленьких компонентів. Ви навчилися делегувати!

🔮 Тизер наступного уроку: А що робити, якщо у нас 50 рівнів вкладеності? Або якщо дані потрібні двом компонентам, які знаходяться в абсолютно різних кутках програми і не мають спільного батька поруч? Невже передавати пропси через весь додаток? Ні. На наступному уроці ми поговоримо про "Телепорт даних" — Context API та Global State Management.


Це був CS50... тобто, ваш урок з React. Побачимось! 👋