← Усі статті

Декларативні залежності полів у формах React

Замість спагеті з useEffect — конфіг залежностей, патерн «спостерігач» і дрібнозерниста реактивність на MobX.

Декларативні залежності полів у формах React
Зміст

Коротко

На Dev.to описано підхід до складних форм на React: залежності полів описують у конфігурації, а не в ланцюжках useEffect.

Поля «підписуються» одне на одне (патерн «спостерігач»). MobX дає дрібнозернисту реактивність — перемальовується лише те, що справді змінилося.

Прототип фармацевтичної форми з десятками полів помітно спростив код. Правила стали читабельними навіть для колег поза клієнтською частиною.

Що сталося

У корпоративних застосунках форми рідко бувають «трьома полями введення»: реєстрація, оформлення замовлення, опитування, введення даних.

Типовий біль — залежність полів: країна показує штат, тип заявки звужує типи подання, комбінації значень вмикають перевірки чи попередження.

Стандартний шлях у ReactuseEffect на кожну зміну. На п’яти полях це ще читається.

На тридцяти з перехресними ланцюжками виходить спагеті: нескінченні цикли, крихкі тести, страх додати ще одне правило.

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

Автор згадує старий XML-каркас інтерфейсу, де залежність писали декларативно (dependsOn, loadFrom, clearOnChange) без ручних обробників.

Сучасний React декларує розмітку, але логіку зв’язків полів частіше пишуть імперативно. Альтернатива в статті — масив моделі форми.

У поля явно вказані subscribesTo / subscribesOn, звідки вантажити варіанти (loadDataFrom) і коли показувати (visibleWhen). Читаєш зверху вниз — бачиш контракт форми.

Для команди це ще й спосіб обговорювати бізнес-правила однією мовою з серверною стороною.

Щоб це працювало, потрібен механізм «поле A змінилось → зацікавлені поля дізнались». Наївний обхід усіх полів після кожного натискання клавіші на 30+ полях гальмує.

Рішення — патерн «спостерігач» плюс сховище з дрібнозернистою реактивністю. Автор порівнює Redux/Zustand з MobX і збирає функціональні сховища без класів.

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

Автор чесно пише, що налагодження рушія складніше, ніж трасування одного явного useEffect. Зате контракт форми перестає бути розмазаним по компонентах.

Чому це важливо

Складні форми — не ніша фарми. Ті самі патерни у фінансових сервісах, держпослугах, інтернет-торгівлі і внутрішніх панелях.

Імперативні ефекти погано масштабуються як документація. Розробник серверної частини не «прочитає» бізнес-правила з десятка useEffect.

Конфіг як дані простіше рецензувати, переносити між режимами перегляд/редагування і частково генерувати з сервера.

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

Є й ціна: власний формат конфігурації, крива навчання, складніше налагодження рушія підписок. Частина правил усе одно піде в імперативний код.

Для простої форми з однією залежністю «країна → місто» накладні витрати бібліотеки не окупляться. Підхід окупається на великих формах із повторюваними ланцюжками.

Підхід Як описані зв’язки Типовий ризик
Ланцюжки useEffect У коді ефектів Приховані цикли, крихкі правки
Конфіг + підписки У даних моделі Крива навчання рушію
Лише бібліотека значень Частково в коді Зв’язки все одно вручну

На практиці

Якщо форма вже розрослась до «ефектів, що смикають ефекти», спочатку опишіть залежності на папері.

Часто виявляється, що половина правил — це дві повторювані операції: показати поле й оновити список варіантів.

Має сенс спочатку описати ці дві дії в конфігу, а вже потім вирішувати, чи потрібна окрема бібліотека, чи вистачить тонкого шару поверх поточних форм.

  1. Випишіть граф: яке поле на що впливає (видимість, перезавантаження списку, скидання значення, правило перевірки).
  2. Виділіть дві часті дії: показати/сховати та оновити дані залежного списку.
  3. Для великих форм оцініть дрібнозернисту реактивність (MobX або аналог).
  4. Тестуйте правила підписок як чисті дані — окремо від монтування компонентів React.
  5. Не відкидайте Formik / React Hook Form: вони добре тримають значення й відправку; декларативні залежності — про зв’язки.

Окремо вирішіть, де живе джерело правди: лише в клієнтському конфігу чи його можна частково віддавати з API. Другий варіант сильніше окупається, якщо форм багато і вони схожі.

Якщо команда вже сидить на Formik або React Hook Form, не викидайте їх заради «чистоти» — додайте шар залежностей поверх, а не замість.

Підсумок

Декларативні залежності полів не скасовують useEffect назавжди.

Вони переносять «хто на кого впливає» з імперативного шуму в читабельний конфіг. На прототипі фармацевтичної форми це скоротило обсяг логіки й зробило правила зрозумілішими команді.

Беріть патерн там, де складність уже болить, а не як моду на кожен екран входу.

Якщо форма ще проста — залиште явні ефекти. Якщо граф залежностей уже не вміщується в голові одного розробника, конфіг і підписки окупаються швидше, ніж ще один шар useEffect.