nmk

Практична робота №4 (2 години)

Тема: Валідація введених даних

Мета: Навчитися працювати з формами в React, опанувати концепцію керованих компонентів (controlled components) та реалізувати кастомну логіку валідації без використання сторонніх бібліотек для глибокого розуміння процесів обробки даних.

Необхідні інструменти: Проєкт, розроблений на попередніх заняттях (Vite + React), редактор коду (VS Code).

План заняття

  1. Підготовка (Git branch)
  2. Керовані компоненти (Controlled Components)
  3. Валідація в реальному часі
  4. Обробка відправки форми
  5. Фіксація змін (Git)

Хід виконання роботи

На цьому занятті ми додамо функціонал додавання нового студента до нашого списку, забезпечивши перевірку коректності введених даних (імені, балів тощо).

1. Підготовка (Git branch)

Створіть нову гілку для роботи з формами:

git checkout -b feature/form-validation

2. Керовані компоненти (Controlled Components)

У React стан форми зазвичай зберігається в state компонента.

  1. Створіть новий компонент AddStudentForm.jsx.
  2. Використовуйте useState для кожного поля (ім’я, бал) або один об’єкт для всієї форми.
  3. Прив’яжіть значення value інпутів до стану та додайте обробник onChange.

3. Валідація в реальному часі

Реалізуйте перевірку даних перед тим, як дозволити їх збереження.

  1. Створіть стан errors (об’єкт) для зберігання повідомлень про помилки.
  2. Напишіть функцію валідації, яка перевіряє:
    • Чи не є поле імені порожнім.
    • Чи введений бал знаходиться в межах від 0 до 100.
  3. Виводьте повідомлення про помилки червоним кольором під відповідними інпутами, використовуючи умовний рендеринг &&.

Для створення надійної форми необхідно реалізувати три аспекти:

3.1. Створення функції валідації

Функція валідації повинна приймати об’єкт із даними форми та повертати об’єкт із помилками. Якщо поле проходить перевірку, відповідний ключ в об’єкті помилок залишається порожнім.

Приклад логіки валідації:

const validate = (values) => {
  const errors = {};

  // Перевірка імені
  if (!values.name.trim()) {
    errors.name = "Ім'я є обов'язковим для заповнення";
  } else if (values.name.length < 2) {
    errors.name = "Ім'я повинно містити принаймні 2 символи";
  }

  // Перевірка балів (від 0 до 100)
  if (values.score === "") {
    errors.score = "Будь ласка, введіть бал";
  } else if (isNaN(values.score) || values.score < 0 || values.score > 100) {
    errors.score = "Бал повинен бути числом від 0 до 100";
  }

  return errors;
};

3.2. Інтеграція у компонент AddStudentForm

Використовуйте раніше створений компонент Input та стан для відстеження помилок.

Покроковий алгоритм у коді:

import { useState } from "react";
import Input from "./atoms/Input"; // Використовуємо ваш компонент
import Button from "./atoms/Button";

function AddStudentForm({ onAddStudent }) {
  const [formData, setFormData] = useState({ name: "", score: "" });
  const [errors, setErrors] = useState({});

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData({ ...formData, [name]: value });

    // Очищення помилки під час введення (опціонально)
    if (errors[name]) {
      setErrors({ ...errors, [name]: "" });
    }
  };

  const handleSubmit = (e) => {
    e.preventDefault();

    // Виклик валідації перед відправкою
    const validationErrors = validate(formData);

    if (Object.keys(validationErrors).length === 0) {
      // Якщо помилок немає — додаємо студента
      onAddStudent({
        id: Date.now(),
        name: formData.name,
        score: Number(formData.score),
      });
      setFormData({ name: "", score: "" }); // Очищення форми
    } else {
      setErrors(validationErrors); // Відображення помилок
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <Input
        label="Прізвище та ім'я:"
        name="name"
        value={formData.name}
        onChange={handleChange}
        placeholder="Введіть ПІБ"
      />

      {/* Використання умовного рендерингу для помилок */}
      {errors.name && <p style=>{errors.name}</p>}

      <Input
        label="Бал студента:"
        name="score"
        type="number"
        value={formData.score}
        onChange={handleChange}
        placeholder="0-100"
      />
      {errors.score && <p style=>{errors.score}</p>}

      <Button type="submit">Додати студента</Button>
    </form>
  );
}

3.3. Методичні поради щодо виконання

3.4. Контрольна перевірка (Self-check)

Перед завершенням роботи перевірте:

4. Обробка відправки форми

  1. Додайте обробник onSubmit до тегу <form>.
  2. Використовуйте event.preventDefault(), щоб запобігти перезавантаженню сторінки.
  3. Якщо помилок немає, передайте дані нового студента у батьківський компонент (через пропси) для оновлення списку.

5. Фіксація змін (Git)

  1. Додайте зміни:
    git add .
    
  2. Зробіть коміт:
    git commit -m "feat: implement student form with validation"
    
  3. Злийте зміни в основну гілку main.

Завдання для самостійного виконання

  1. Блокування кнопки: Зробіть кнопку “Додати” неактивною (disabled), якщо форма містить помилки або обов’язкові поля не заповнені.
  2. Типізація вводу: Додайте перевірку на тип даних (наприклад, щоб у поле “Бал” не можна було ввести літери чи символи).

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

  1. У чому головна різниця між керованими (controlled) та некерованими (uncontrolled) компонентами?
  2. Навіщо використовувати useRef при роботі з формами і в яких випадках це виправдано?
  3. Чому важливо викликати event.preventDefault() при обробці події submit?

Результат заняття

Реалізована форма з валідацією, яка дозволяє динамічно додавати нові об’єкти до інтерфейсу, гарантуючи цілісність та коректність даних.