Можно ли сделать общий стейт для формы, чтобы получать значения по имени поля
Что проверяют
Знаете ли вы, как в React устроены управляемые поля, и понимаете ли цену одного общего объекта состояния. По ответу видно, писали ли вы формы сложнее формы входа.
Как отвечать
Да, это обычный приём: одно состояние-объект и общий обработчик, который пишет значение по атрибуту name через вычисляемый ключ.
const [values, setValues] = useState({ email: "", agree: false });
const onChange = (e) => {
const { name, value, type, checked } = e.target;
setValues((prev) => ({ ...prev, [name]: type === "checkbox" ? checked : value }));
};Дальше покажите, что вариант не один:
- если значения нужны только при отправке, состояние не нужно совсем:
new FormData(form)иObject.fromEntriesдадут тот же объект по именам полей; - логика с зависимыми полями и валидацией аккуратнее ложится на
useReducer; - большие формы отдают библиотеке, которая держит поля неуправляемыми и перерисовывает только изменившееся.
Главный компромисс назовите сами: общий объект означает перерисовку всей формы на каждое нажатие клавиши. Для десятка полей это незаметно, для формы с таблицей внутри уже нет.
Где спотыкаются
Первое: обновляют состояние из старой копии, setValues({ ...values, [name]: value }). Пока событие одно, работает, но при нескольких обновлениях подряд или в асинхронном обработчике часть правок теряется. Функциональная форма обновления от этого избавляет.
Второе: считают, что значение у всех полей лежит в value. У чекбокса оно в checked, у файла в files, поле с типом number отдаёт строку, а множественный выбор массив. Обработчик на все поля без разбора типа тихо пишет в состояние мусор.
Третье: ловят предупреждение о переходе поля из неуправляемого в управляемое. Оно означает, что ключа в состоянии не было и в value приехал undefined. Лечится полным начальным объектом или подстраховкой вида value={values[name] ?? ""}.