nmk

Лабораторне заняття №16 (2 години). Реалізація складних форм у React.

Мета

Опанувати концепцію “Керованих компонентів” (Controlled Components) у React. Навчитися прив’язувати стан форми до хука useState, обробляти зміни полів вводу (onChange) та кастомно валідувати дані (наприклад, форму оформлення замовлення Checkout з ПР №6) перед їхньою відправкою onSubmit.

План

  1. Створення компонента CheckoutForm.jsx.
  2. Ініціалізація стану форми через useState (об’єкт formData).
  3. Прив’язка значень інпутів до стану (value={formData.fullName}).
  4. Написання універсального обробника handleChange для всіх текстових полів.
  5. Перехоплення події onSubmit та скасування стандартної поведінки браузера (e.preventDefault()).

Хід роботи

Увага: Продовжуємо роботу над інтернет-магазином “TechShop” на React. Якщо раніше форма у checkout.html надсилала дані напряму на сервер (і сторінка перезавантажувалась), то тепер ми маємо повний контроль над даними завдяки useState.

  1. Створення Компонента Форми:
    • У папці components створіть файл CheckoutForm.jsx.
    • Перенесіть туди вашу HTML-розмітку форми оформлення замовлення з ПР №6. Одразу виправте атрибути: class на className, for (у мітках) на htmlFor.
  2. Ініціалізація Стану (State):
    • У компоненті імпортуйте useState з React.
    • Створіть ОДИН об’єкт стану formData для збереження значень усіх полів, щоб не створювати 10 окремих змінних:

      import { useState } from "react";
      
      export function CheckoutForm() {
        const [formData, setFormData] = useState({
          fullName: "",
          email: "",
          phone: "",
          delivery: "nova_poshta",
          city: "kyiv",
          comment: "",
        });
      
        // Інший код...
      }
      
  3. Універсальний обробник handleChange:
    • Напишіть функцію, яка спрацьовуватиме при кожному натисканні клавіші в будь-якому <input> чи <select>.

      const handleChange = (e) => {
        // Деструктуруємо властивості події (який інпут був змінений і що в нього ввели)
        const { name, value, type, checked } = e.target;
      
        // Якщо це чекбокс - беремо checked, інакше - value
        const finalValue = type === "checkbox" ? checked : value;
      
        setFormData((prevState) => ({
          ...prevState, // Копіюємо всі попередні дані: ПІБ, Місто, Телефон...
          [name]: finalValue, // Перезаписуємо лише ТЕ поле, ім'я (name="") якого співпало!
        }));
      };
      
  4. Прив’язка до JSX (Контрольований компонент):
    • У вашій формі кожен елемент <input> повинен мати дві властивості: value (щоб React показував значення зі стану) та onChange (щоб React знав, що робити при введенні тексту). Крім того, атрибут name МУСИТЬ відповідати ключам в об’єкті formData (напр., “fullName”, “email”).
      {
        /* Приклад з ПІБ */
      }
      <input
        type="text"
        id="fullName"
        name="fullName"
        value={formData.fullName}
        onChange={handleChange}
        required
      />;
      
  5. Обробка Submit (Відправка):
    • Додаємо слухач на сам тег <form onSubmit={handleSubmit}>.
    • Напишіть функцію handleSubmit:

      const handleSubmit = (e) => {
        e.preventDefault(); // Дуже важливо! Зупиняє перезавантаження сторінки
      
        // Валідація (наприклад, перевірка чи номер містить більше 10 цифр)
        if (formData.phone.length < 10) {
          alert("Номер телефону занадто короткий!");
          return; // Зупиняємо функцію
        }
      
        // Якщо все добре:
        console.log("Дані готові до відправки на бекенд:", formData);
        alert(`Дякуємо за замовлення, ${formData.fullName}!`);
      };
      
  6. Збереження (Commit & Push):
    • Перевірте відображення: додайте <CheckoutForm /> в App.jsx. Заповніть форму, натисніть “Підтвердити” і подивіться в консоль — ви побачите красиво зібраний JS-об’єкт.
    • Виконайте git add . та git commit -m "Create controlled Checkout Form using useState".
    • Запушіть у свою гілку та злийте в main.

Результат

Форма замовлення “TechShop” стала “Керованою”. Жоден символ не може бути надрукований на екрані без відома React. Ми зібрали всі дані в єдиний об’єкт, готовий для відправки через fetch() на сервер у майбутньому.

Контрольні питання

  1. Чому компонент називається “Керованим” (Controlled)? Хто ним керує і що є єдиним джерелом правди (Single Source of Truth) для форми?
  2. Навіщо у функції handleChange ми використовуємо [name]: value у квадратних дужках? Як це називається в JavaScript (Обчислювальні імена властивостей - Computed property names)?
  3. Що сталося б, якби ми забули написати ...prevState перед оновленням конкретного поля? Що залишилося б у нашому об’єкті formData після введення імені?
  4. Для чого слугує метод e.preventDefault(), який ми викликаємо першим у перехоплювачі handleSubmit? Розкажіть про стандартну поведінку тегу <form>.
  5. Чим атрибут htmlFor в React відрізняється від for у звичайному HTML, і чому слово for не можна використовувати в JSX?