> Почему форма отправляется два раза при сабмите в React (React, JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Milk and Cartoons
Стек: React, JavaScript
> Пример ответа
Короткий ответ
Двойная отправка формы в React возникает из-за того, что обработчик submit вызывается дважды: один раз при клике на кнопку типа submit (событие click) и второй раз при отправке формы (событие submit). Это происходит, когда кнопка находится внутри формы и не вызван event.preventDefault() в обработчике submit, либо когда обработчик submit привязан и к форме, и к кнопке.
Подробное объяснение
В React форма может отправляться дважды по нескольким причинам. Основная - неправильная обработка событий. Когда пользователь кликает на <button type="submit"> внутри <form>, браузер генерирует два события: click на кнопке и submit на форме. Если оба события обрабатываются и каждый вызывает отправку данных (например, через fetch или axios), происходит двойной запрос.
Другая распространенная причина - использование onSubmit на форме вместе с onClick на кнопке без предотвращения распространения. В React события синтетические, но они все равно всплывают. Если обработчик onClick на кнопке вызывает event.stopPropagation(), это может не остановить submit событие формы, так как это разные события.
Также проблема может быть связана с Strict Mode в React 18, который дважды монтирует компоненты в development режиме для обнаружения побочных эффектов. Если эффект с подпиской на событие submit не очищается корректно, обработчик может быть зарегистрирован дважды.
Еще один сценарий - использование useEffect для подписки на событие submit без правильной очистки. При повторном рендере создается новая подписка, а старая не удаляется, что приводит к множественным вызовам.
На практике
Для предотвращения двойной отправки:
- Всегда используйте
event.preventDefault()в обработчикеonSubmitформы - Не добавляйте обработчики
onClickна кнопку submit, если уже естьonSubmitна форме - Если нужно обработать клик на кнопке отдельно, используйте
type="button"вместоtype="submit" - В
useEffectвсегда возвращайте функцию очистки для удаления подписок - Используйте флаг
isSubmittingили disable кнопки после первого клика
Пример кода
JSX// Проблемный кодfunction BadForm() {const handleSubmit = (e) => {// Нет preventDefaultfetch('/api/data', { method: 'POST', body: new FormData(e.target) });};const handleClick = () => {fetch('/api/data', { method: 'POST' }); // Двойной запрос!};return (<form onSubmit={handleSubmit}><button onClick={handleClick} type="submit">Отправить</button></form>);}// Исправленный кодfunction GoodForm() {const [isSubmitting, setIsSubmitting] = useState(false);const handleSubmit = async (e) => {e.preventDefault();if (isSubmitting) return;setIsSubmitting(true);try {await fetch('/api/data', { method: 'POST', body: new FormData(e.target) });} finally {setIsSubmitting(false);}};return (<form onSubmit={handleSubmit}><button type="submit" disabled={isSubmitting}>{isSubmitting ? 'Отправка...' : 'Отправить'}</button></form>);}
Как отвечать на собеседовании
Начните с основной причины - дублирование событий click и submit. Затем перечислите другие возможные причины: Strict Mode, неправильная очистка эффектов, отсутствие preventDefault. Приведите пример исправления с использованием флага isSubmitting и disable кнопки. Упомяните, что в production Strict Mode не влияет. Покажите понимание разницы между синтетическими и нативными событиями в React.
Что проверяет интервьюер
- Понимание event loop и bubbling в DOM
- Знание особенностей React SyntheticEvent
- Умение работать с формами и предотвращать побочные эффекты
- Понимание Strict Mode и его влияния на разработку
- Навыки отладки и поиска причин дублирования запросов
Типичные ошибки
- Использование
onClickна кнопке submit вместе сonSubmitна форме - Отсутствие
event.preventDefault()в обработчике submit - Игнорирование Strict Mode при тестировании
- Неправильная очистка
useEffectс подписками на события - Использование
event.stopPropagation()вместоevent.preventDefault()
> Похожие задачи по frontend
В чем разница useRef и useState в React
Что делают хуки useSelector и useDispatch в Redux
Был ли у вас опыт работы с React Native?
Что такое глобальное состояние в React
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью