Чому ти не повинен використовувати onChange у React (без вагомих причин)

React

Одним із найпоширеніших способів обробки вводу даних у React є використання атрибуту onChange. Цей атрибут дозволяє відслідковувати зміни в елементах форм, таких як текстові поля, прапорці або випадаючі списки. На перший погляд, onChange виглядає як зручний інструмент, але в певних випадках він може створювати проблеми з продуктивністю, ускладнювати код та навіть порушувати принципи React.

У цій статті ми розглянемо, чому варто уникати onChange, якщо це можливо, а також які альтернативи можуть бути корисними для вирішення проблем із обробкою вводу.

Що таке onChange у React?

onChange — це атрибут, який використовується для обробки подій зміни значення елемента форми. Коли користувач вводить дані у текстове поле або змінює стан прапорця, onChange викликає функцію-обробник.

Приклад з onChange:

function TextInput() {
  const [value, setValue] = React.useState('');

  const handleChange = (event) => {
    setValue(event.target.value);
  };

  return (
    <input type="text" value={value} onChange={handleChange} />
  );
}

Чому onChange може бути проблемним?

1. Часте викликання функцій

onChange викликається при кожному введенні символу або зміні стану елемента. У великих додатках це може призводити до надмірного рендерингу компонентів, що впливає на продуктивність.

Проблема:

  • Якщо ви оновлюєте стан у кожному виклику onChange, це може створювати затримки та навантаження на рендеринг.

Приклад проблеми:

function App() {
  const [text, setText] = React.useState('');

  console.log('Компонент рендериться');

  return (
    <input
      type="text"
      value={text}
      onChange={(e) => setText(e.target.value)}
    />
  );
}

У цьому прикладі кожне введення символу викликає оновлення стану і повторний рендер компонента.

2. Потенційна втрата контролю над даними

У сценаріях із великими формами onChange може ускладнювати управління станом, особливо якщо обробка вводу залежить від кількох компонентів.

Проблема:

  • Коли одна функція onChange відповідає за обробку багатьох елементів форми, це може створити заплутаний код.

3. Зайва логіка у функції-обробнику

У багатьох випадках функція onChange починає накопичувати додаткову логіку, наприклад, перевірку введених даних, форматування або валідацію.

Проблема:

  • Логіка перевірки та обробки даних ускладнює читабельність коду і може створити вузькі місця.

4. Висока ймовірність помилок

Неправильне використання onChange може призвести до некоректної поведінки додатка, наприклад, некоректного синхронізування стану або пропуску змін.

Коли можна уникати onChange?

1. Використовуйте обробку подій на формі

Для великих форм краще обробляти дані на рівні всієї форми, а не кожного елемента.

Приклад:

function Form() {
  const handleSubmit = (event) => {
    event.preventDefault();
    const formData = new FormData(event.target);
    console.log(Object.fromEntries(formData));
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="username" type="text" placeholder="Ім'я користувача" />
      <input name="email" type="email" placeholder="Email" />
      <button type="submit">Відправити</button>
    </form>
  );
}

2. Ліниве оновлення стану

Замість негайного оновлення стану при кожному введенні символу, можна оновлювати стан після певної події (наприклад, натискання кнопки).

Приклад:

function LazyUpdate() {
  const [input, setInput] = React.useState('');
  const [finalValue, setFinalValue] = React.useState('');

  const handleSave = () => {
    setFinalValue(input);
  };

  return (
    <div>
      <input
        type="text"
        value={input}
        onChange={(e) => setInput(e.target.value)}
      />
      <button onClick={handleSave}>Зберегти</button>
      <p>Збережене значення: {finalValue}</p>
    </div>
  );
}

3. Використовуйте бібліотеки для форм

Бібліотеки, такі як Formik, React Hook Form або Final Form, забезпечують зручний інструментарій для роботи з формами без потреби вручну обробляти події onChange.

Приклад із React Hook Form:

import { useForm } from 'react-hook-form';

function FormWithHook() {
  const { register, handleSubmit } = useForm();

  const onSubmit = (data) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('username')} placeholder="Ім'я користувача" />
      <input {...register('email')} type="email" placeholder="Email" />
      <button type="submit">Відправити</button>
    </form>
  );
}

Коли все ж використовувати onChange?

Є випадки, коли onChange — це найкращий вибір:

  1. Прості форми: Коли форма містить один або кілька простих елементів.
  2. Миттєве оновлення: Коли потрібно динамічно змінювати інші частини UI залежно від вводу.

Приклад:

function DynamicUI() {
  const [color, setColor] = React.useState('');

  return (
    <div>
      <input
        type="text"
        placeholder="Введіть колір"
        onChange={(e) => setColor(e.target.value)}
      />
      <div style={{ backgroundColor: color, height: '100px', width: '100px' }} />
    </div>
  );
}

Висновок

onChange — це потужний інструмент у React, але його використання має бути виправданим. Уникайте надмірного використання цього атрибуту у складних формах і великих додатках. Замість цього зосередьтеся на більш ефективних підходах, таких як обробка на рівні форми, ліниве оновлення або використання спеціалізованих бібліотек.

Дотримуючись цих рекомендацій, ви зможете створювати швидкі та зручні додатки з чистим і зрозумілим кодом.