handleSubmit calls onSubmit again while a submit is still pending (since 1.33.1)

Ouverte Adaptée aux débutants
#2,467 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

@twotnguyen y travaille déjà.

Depuis le 7/11/2026.

  • #2470 par @twotnguyen — ouverte

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
78/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
react, typescript
Domaine
frontend

Piste de recherche

Le rapport signale _handleSubmit et this.baseStore.state.isSubmitting dans @tanstack/form-core ; commencez par suivre le retour anticipé et la vérification de la tentative de soumission décrits dans l’issue. Reproduisez le problème avec le script Node fourni sur le code actuel, puis ajoutez ou mettez à jour un test de régression pour une deuxième soumission pendant un onSubmit en attente ; le travail est terminé lorsque onSubmit n’est appelé qu’une seule fois et que le comportement de nouvelle soumission de #2120 est préservé.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

Describe the bug

Since #2120 ("clear stale onBlur errors on re-submission", released in 1.33.1), handleSubmit skips its !canSubmit early return on every attempt after the first. canSubmit is also false while a submit is in flight, so a second handleSubmit during a pending onSubmit now runs validation and calls onSubmit again. Up to 1.33.0 that second call returned early.

In practice: a double tap on a submit button, or Enter / the keyboard's "go" pressed twice, sends the request twice. We hit it on a sign-in form and a comment composer in React Native, where the keyboard submit bypasses a disabled button.

Your minimal, reproducible example

No sandbox, it needs only @tanstack/form-core in Node:

// npm i @tanstack/[email protected], then: node repro.mjs
import { FormApi } from '@tanstack/form-core';

const pending = [];
const form = new FormApi({
  defaultValues: { name: 'Ada' },
  onSubmit: () => new Promise((resolve) => pending.push(resolve)),
});
form.mount();

const first = form.handleSubmit();
await new Promise((resolve) => setTimeout(resolve, 0));
console.log('isSubmitting:', form.state.isSubmitting, 'canSubmit:', form.state.canSubmit);

const second = form.handleSubmit();
await new Promise((resolve) => setTimeout(resolve, 0));

console.log('onSubmit calls:', pending.length, '(expected 1)');
pending.forEach((resolve) => resolve());
await Promise.all([first, second]);
Steps to reproduce
  1. Run the script with @tanstack/[email protected]: isSubmitting: true canSubmit: false, onSubmit calls: 1.
  2. Run it with @tanstack/[email protected]: same state, onSubmit calls: 2.
Expected behavior

A handleSubmit that arrives while isSubmitting is true does not call onSubmit again, as before #2120. Keeping the re-submission behaviour #2120 added and also returning early when this.baseStore.state.isSubmitting is true would cover both.

How often does this bug happen?

Every time

Platform
  • @tanstack/form-core 1.33.5 (via @tanstack/react-form 1.33.5)
  • Node 26, and React Native 0.88 / Hermes in the app
TanStack Form adapter

react-form

TanStack Form version

1.33.5

TypeScript version

5.9

Additional context

The change is in _handleSubmit: if (!this.state.canSubmit && ...) { if (this.baseStore.state.submissionAttempts <= 1) { ...; return; } }. We now wrap onSubmit in a single-flight guard on our side.

Langage dominant
TypeScript
Étoiles
6.8k
Forks
711
Merge moyen
1 j 6 h
PR mergées (30 j)
12

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de TanStack/form

Toutes les issues de TanStack/form

Issues similaires

Plus d'issues TypeScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.