Ось готовий урок, згенерований за твоїм майстер-промптом. Я намагався зберегти енергетику лекційної зали Гарварду, але адаптувати це для формату текстового уроку.
🎓 CS50: React. Форми та Контрольовані компоненти
Всім привіт! Радий вас бачити. 👋
Сьогодні ми поговоримо про те, як наші програми спілкуються з людьми. До цього моменту ми здебільшого просто показували щось на екрані: картинки, текст, списки. Але веб — це не телевізор. Це діалог.
Як користувач каже вам: "Я хочу купити цей квиток" або "Мене звати Олексій"? Через форми.
І тут починається найцікавіше. Тому що в React форми працюють зовсім не так, як ви звикли у звичайному HTML.
1. 🔥 Вступ: Хто тут головний?
Уявіть, що ви заповнюєте паперову анкету в банку. Ви пишете своє ім'я ручкою. Чи знає банк, що ви написали помилку в слові, поки ви не віддали їм папірець? Ні. Чи може банк заборонити вам написати цифру "5" у полі для імені в момент написання? Ні. Ви вже це написали.
Це — старий підхід (Uncontrolled). HTML сам тримає в собі те, що ви ввели.
А тепер проблема:
У сучасному вебі ми хочемо миттєвої реакції.
* Ви ввели слабкий пароль? Ми хочемо підсвітити його червоним одразу.
* Ви вибрали країну "Україна"? Ми хочемо автоматично змінити код телефону на +380.
* Ви натиснули "Надіслати"? Ми хочемо перевірити дані до того, як вони полетять на сервер.
Якщо ми дозволимо браузеру самому керувати інпутом (полем вводу), ми втратимо цей контроль. Ми будемо дізнаватися про зміни занадто пізно.
Риторичне питання: Хто має керувати даними на екрані — випадковий HTML-тег чи наш логічний React-код?
Відповідь очевидна: Ми хочемо повного контролю.
2. 🧠 Теоретична база: "Єдине джерело істини"
У React є концепція, яку ви маєте викарбувати у пам'яті: Single Source of Truth (Єдине джерело істини).
У звичайному HTML:
1. Ви натискаєте клавішу A.
2. Браузер малює A в інпуті.
3. Потім (можливо) ви зчитуєте це значення.
У React (Контрольований компонент):
1. Ви натискаєте клавішу A.
2. React перехоплює це і каже: "Стоп. Нічого не малюй, поки я не дозволю".
3. React оновлює свій State (стан).
4. React наказує інпуту: "Окей, у стейті тепер є 'A', тепер можеш показати 'A'".
Що це означає "під капотом"?
Це виглядає як замкнене коло.
* State керує тим, що бачить користувач (value).
* Користувач намагається щось змінити.
* Ми перехоплюємо це через подію (onChange).
* Ми оновлюємо State.
* Коло замикається.
📌 Запам'ятайте обов'язково:
Інпут у React не зберігає своє значення сам. Він лише відображає те, що лежить у змінній стану (
useState).
Аналогія: Це як телесуфлер. Ведучий новин (інпут) не говорить від себе. Він говорить лише те, що написано на екрані суфлера (State). Якщо ми змінимо текст на суфлері — зміниться і те, що скаже ведучий.
3. 🧪 Приклади: Від простого до реального
Приклад 1: Найпростіший контрольований інпут
Давайте подивимось на код. Що ви очікуєте побачити, якщо ми спробуємо зв'язати useState та <input>?
import { useState } from 'react';
function NameForm() {
const [name, setName] = useState(''); // 1. Створили стейт
return (
<div>
<label>Ваше ім'я:</label>
<input
type="text"
value={name} // 2. Прив'язали значення до стейту
onChange={(e) => setName(e.target.value)} // 3. Оновлюємо стейт при введенні
/>
<p>Привіт, {name}!</p>
</div>
);
}
Як це працює:
Як тільки ви натискаєте кнопку, спрацьовує onChange. Ми беремо e.target.value (те, що ви хотіли ввести) і кладемо це в setName. React бачить новий стейт, перемальовує компонент і вставляє нове значення в value. Це відбувається за мілісекунди.
Приклад 2: "А що, якщо..." (Пастка для новачків)
А тепер я приберу один рядок. Подивіться уважно.
<input
type="text"
value={name}
// onChange видалено!
/>
Питання до вас: Що станеться, коли я спробую щось надрукувати в цьому полі? (Пауза для роздумів)
Результат: Ви будете шалено бити по клавіатурі, але в полі нічого не з'явиться. Воно буде "заморожене".
Чому? Тому що React каже: "Значення цього поля дорівнює name. name — порожнє. Ти не дав мені інструкції (onChange), як змінювати name. Тому я буду вічно показувати порожній рядок, що б ти не робив".
Приклад 3: Реальна ситуація (Валідація)
Навіщо нам цей контроль? Щоб робити магію. Давайте заборонимо вводити більше 10 символів і зробимо текст червоним, якщо там є пробіли.
function PasswordInput() {
const [password, setPassword] = useState('');
const handleChange = (e) => {
const newValue = e.target.value;
// Ми контролюємо ситуацію! Не дозволяємо ввести більше 10 символів.
if (newValue.length <= 10) {
setPassword(newValue);
}
};
const hasSpace = password.includes(' ');
return (
<div>
<input
type="password"
value={password}
onChange={handleChange}
style={{ borderColor: hasSpace ? 'red' : 'black' }} // Динамічні стилі
/>
{hasSpace && <small style={{color: 'red'}}>Пароль не може містити пробіли!</small>}
</div>
);
}
Бачите? Ми не чекаємо "відправки форми". Ми реагуємо миттєво. Це і є сучасний UX (User Experience).
4. 🛠 Практична частина
Прийшов час забруднити руки кодом. Відкривайте редактор!
Завдання 1: Дзеркало
Створіть компонент з одним input. Нижче під ним створіть текст, який у реальному часі пише те саме, що ви вводите, але у верхньому регістрі (CAPS LOCK).
Підказка: метод .toUpperCase().
Завдання 2: Кнопка "Очистити"
Додайте до попереднього завдання кнопку "Очистити". При кліку на неї поле вводу має стати порожнім.
Питання: чи потрібно вам шукати інпут через document.querySelector? Чи достатньо просто змінити стейт?
Завдання 3: Чекбокс згоди
Створіть форму з чекбоксом "Я погоджуюсь з правилами" і кнопкою "Надіслати".
Кнопка "Надіслати" має бути неактивною (disabled), доки галочка не стоїть.
Підказка: для чекбокса використовуйте e.target.checked, а не e.target.value.
Завдання 4: Міні-кейс "Конвертер валют" Зробіть два інпути: "Гривні" та "Долари". Курс — 40. * Якщо вводите в гривні — автоматично перераховуються долари. * Якщо вводите в долари — автоматично перераховуються гривні. Це вимагає трохи математики і, можливо, двох станів або розумної логіки!
5. 💡 Мислення як у розробника
Як думає досвідчений React-розробник, коли бачить форми?
-
"Де живе істина?" Новачки часто намагаються зчитувати значення з DOM в момент натискання кнопки (як в jQuery). Профі думає: "У мене є стейт
userData. Форма — це просто красивий спосіб наповнити цей стейт". -
Уникайте дублювання стейту. Якщо у вас є
firstNameіlastName, не створюйте третій стейтfullName. Краще просто обчисліть його прямо під час рендеру:const fullName = firstName + ' ' + lastName;Менше змінних — менше багів. -
Об'єднання. Якщо у вас форма на 20 полів, не робіть 20 змінних
useState. Зробіть один об'єкт:javascript const [formData, setFormData] = useState({ firstName: '', email: '', city: '' });Це значно чистіше.
6. 🧩 Підсумок
Отже, що ми сьогодні розібрали?
- Ми відібрали владу у браузера і передали її React-у через Контрольовані компоненти.
- Ми зрозуміли мантру: State -> Value -> onChange -> State.
- Ми навчилися робити форми, які допомагають користувачеві, а не дратують його.
Тепер ви вмієте збирати дані. Ваші компоненти "чують" користувача.
Але ось загадка на майбутнє:
Добре, дані у нас в змінній formData. Вони "живуть" у браузері клієнта. Але як нам передати їх у великий світ? Як відправити їх на сервер, щоб зберегти в базі даних?
Про це ми поговоримо на наступному уроці, коли будемо розбирати Взаємодію з API та useEffect.
А поки — це був CS50... тобто, урок з React. Кодьте з розумом! 💻