Ось твій урок у стилі CS50. Вмикай енергію на максимум, ми починаємо! 🚀
🎓 Урок: Робота з формами та магія React Hook Form
Привіт, друзі! Це CS50 (умовно 😉), і сьогодні ми поговоримо про те, що є на 99% веб-сайтів.
Це те, через що ми реєструємося, купуємо квитки, пишемо коментарі та відправляємо гроші. Так, це ФОРМИ.
Здавалося б, ну що там складного? <input>, <button>, поїхали. Але якщо ви хоч раз намагалися написати велику форму на "чистому" React, ви знаєте цей біль.
1. 🔥 Вступ: Чому старий спосіб — це пекло?
Уявіть ситуацію. Ви будуєте сторінку оформлення замовлення ("Checkout"). Там є: Ім’я, Прізвище, Адреса, Місто, Індекс, Номер картки... скажімо, 15 полів.
Як ми робили це раніше?
Ми створювали 15 станів (useState), по одному на кожне поле. Або один велетенський об’єкт стану.
І щоразу, коли користувач натискає одну літеру, React перемальовує (робить ре-рендер) весь компонент.
🤯 Риторичне питання: Чи має сенс перемальовувати всю "кухню", якщо ви просто поклали одну ложку на стіл? Звісно, ні!
А тепер додайте сюди валідацію.
"Пароль має бути не менше 8 символів", "Email невалідний".
Вам доведеться писати купу функцій if (password.length < 8) .... Це перетворює ваш код на "спагеті".
Аналогія: Уявіть, що ви заповнюєте паперову анкету в банку. * Стандартний підхід React (Controlled Inputs): Банкір стоїть у вас над душею і вихоплює анкету після кожної написаної літери, щоб перевірити її, а потім віддає назад. Це дратує і це повільно. * React Hook Form (Uncontrolled Inputs): Банкір дає вам анкету і каже: "Заповни, як закінчиш — поклич, я перевірю все разом". Це швидко, ефективно і логічно.
Сьогодні ми навчимося бути "розумним банкіром" за допомогою бібліотеки React Hook Form.
2. 🧠 Теоретична база (Що під капотом?)
React Hook Form (RHF) працює інакше, ніж стандартні форми в React.
Ключова відмінність:
Замість того, щоб React контролював кожне натискання клавіші (Controlled Components), RHF дозволяє браузеру зберігати значення інпуту, а React "підглядає" туди тільки коли треба (Uncontrolled Components).
Головні інструменти (Ваш арсенал):
useForm— це головний хук. Він як менеджер, що керує всім процесом.register— це магічна функція. Вона "реєструє" ваш інпут у системі. Це як видати бейджик співробітнику: "Тепер ти працюєш на мене, я слідкую за тобою".handleSubmit— охоронець на вході. Він не дозволить формі відправитися, доки всі дані не будуть валідними.formState: { errors }— об'єкт, де живуть усі помилки. Якщо користувач накосячив, RHF покладе туди записку з поясненням.
☝️ Що треба зрозуміти інтуїтивно:
Ви не створюєте useState для кожного поля. Ви просто кажете RHF: "Ось інпут, ось його правила (наприклад, обов'язковий). Слідкуй за ним сам".
3. 🧪 Приклади: Від "Hello World" до Реальності
Приклад 1: Мінімальна база
Що ми очікуємо? Просту форму з одним полем, яка виводить дані в консоль.
import { useForm } from "react-hook-form";
export default function SimpleForm() {
// 1. Ініціалізуємо хук
const { register, handleSubmit } = useForm();
// 2. Функція, яка спрацює ТІЛЬКИ якщо все ок
const onSubmit = (data) => console.log("Дані форми:", data);
return (
// 3. handleSubmit обгортає нашу функцію
<form onSubmit={handleSubmit(onSubmit)}>
{/* 4. Реєструємо інпут під іменем "firstName" */}
<input {...register("firstName")} placeholder="Ваше ім'я" />
<button type="submit">Надіслати</button>
</form>
);
}
🔍 Розбір:
Бачите ...register("firstName")? Цей спред-синтаксис (...) автоматично додає інпуту name, onChange, onBlur і ref. Ми не писали жодного useState!
Приклад 2: Додаємо правила (Валідація)
У реальному житті не можна просто дозволити відправити порожнє поле. Давайте додамо вимогу: ім'я обов'язкове.
import { useForm } from "react-hook-form";
export default function ValidationForm() {
const {
register,
handleSubmit,
formState: { errors } // Дістаємо об'єкт помилок
} = useForm();
const onSubmit = (data) => alert(`Привіт, ${data.username}!`);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>Username:</label>
{/* Додаємо об'єкт з правилами другим аргументом */}
<input
{...register("username", { required: "Це поле обов'язкове!" })}
style={{ borderColor: errors.username ? 'red' : 'black' }}
/>
{/* Якщо є помилка в username, показуємо її текст */}
{errors.username && <p style={{color: 'red'}}>{errors.username.message}</p>}
<button type="submit">Увійти</button>
</form>
);
}
Чому це круто?
RHF сам перевіряє інпут. Якщо ви натиснете "Увійти" з порожнім полем, onSubmit навіть не запуститься. Фокус автоматично перестрибне на поле з помилкою. Зручно, правда?
4. 🛠 Практична частина
Час забруднити руки кодом! Відкривайте редактор.
🔹 Завдання 1: Реплікація
Створіть компонент LoginForm, який має два поля: email та password. Виведіть дані в console.log при сабміті.
🔹 Завдання 2: Валідація Email
Додайте до поля email валідацію.
* Воно має бути required.
* Воно має відповідати патерну email (підказка: в register є властивість pattern).
🔹 Завдання 3: "Секретний пароль"
Зробіть так, щоб пароль мав мінімальну довжину 6 символів (minLength). Якщо менше — покажіть текст "Занадто короткий пароль!".
🔹 Завдання 4: Міні-кейс
Створіть чекбокс "Я погоджуюсь з умовами". Кнопка "Реєстрація" має працювати, тільки якщо чекбокс відмічено (це теж робиться через register і required).
🔹 Питання "А що, якщо...":
Що станеться, якщо у двох інпутів в register буде однакове ім'я (наприклад, ...register("user"))? Спробуйте і подивіться, яке значення переможе.
5. 💡 Мислення як у розробника
Як відрізнити новачка від профі, дивлячись на код форми?
1. Новачок:
Намагається контролювати кожен чих.
onChange={(e) => setName(e.target.value)}.
Він бореться з React, замість того щоб використовувати DOM.
2. Досвідчений розробник: Думає про продуктивність (менше ре-рендерів) і DX (Developer Experience — зручність написання коду). Він використовує React Hook Form, тому що це зменшує код на 50% і робить його чистішим.
⚠️ Типова помилка:
Забувати деструктуризувати register або handleSubmit.
Або плутати ім'я поля в register("email") і те, що приходить в onSubmit (там теж буде об'єкт { email: ... }).
Порада:
Завжди дивіться в console.log(errors), коли щось не працює. RHF дуже чітко каже, де проблема.
6. 🧩 Підсумок
Отже, що ми сьогодні зробили?
- Зрозуміли, що контролювати кожен інпут вручну — це минуле століття.
- Познайомилися з
useFormтаregister— нашими новими найкращими друзями. - Навчилися робити валідацію без головного болю та купу
if/else. - Зробили наші додатки швидшими, бо позбулися зайвих рендерів.
Ви тепер вмієте: Створювати форми будь-якої складності, які не "гальмують" і самі себе перевіряють.
🔜 Тизер наступного уроку:
А що, якщо у вас форма на 50 полів і валідація дуже складна (наприклад, "пароль має містити цифру, літеру і смайлик")? Писати правила в register стане незручно.
На наступному уроці ми підключимо "важку артилерію" — бібліотеку схем Zod або Yup, яка зробить вашу валідацію куленепробивною.
А поки що — це був CS50! (тобто наш урок 😉). Кодьте із задоволенням!