T
TanStack5mo ago
rare-sapphire

How to properly output error from useForm onSubmit

const [error, setError] = useState("");
const form = useForm({
defaultValues: {
email: "",
password: "",
},
onSubmit: async ({ value }) => {
const { error } = await authClient.signIn.email({
email: value.email,
password: value.password,
});
setError(error?.message || "Something went wrong");
},
});
const [error, setError] = useState("");
const form = useForm({
defaultValues: {
email: "",
password: "",
},
onSubmit: async ({ value }) => {
const { error } = await authClient.signIn.email({
email: value.email,
password: value.password,
});
setError(error?.message || "Something went wrong");
},
});
4 Replies
rare-sapphire
rare-sapphireOP5mo ago
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<div className="flex flex-col gap-6">
{error && (
<Alert variant="destructive">
<AlertDescription>{error}</AlertDescription>
</Alert>
)}

<form.Field
name="email"
children={(field) => (
<div className="grid gap-3">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
placeholder="m@example.com"
required
/>
</div>
)}
/>
<form.Field
name="password"
children={(field) => (
<div className="grid gap-3">
<div className="flex items-center">
<Label htmlFor="password">Password</Label>
</div>
<Input
id="password"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
type="password"
required
/>
</div>
)}
/>
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<div className="flex flex-col gap-6">
{error && (
<Alert variant="destructive">
<AlertDescription>{error}</AlertDescription>
</Alert>
)}

<form.Field
name="email"
children={(field) => (
<div className="grid gap-3">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
placeholder="m@example.com"
required
/>
</div>
)}
/>
<form.Field
name="password"
children={(field) => (
<div className="grid gap-3">
<div className="flex items-center">
<Label htmlFor="password">Password</Label>
</div>
<Input
id="password"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
type="password"
required
/>
</div>
)}
/>
xenial-black
xenial-black5mo ago
put the signIn call in the validators.onSubmitAsync parameter instead. There will be two outcomes: * The Signin has errors. Format them and return the errors in the validator. Tanstack Form will then know that the validators.onSubmitAsync call failed and will not execute onSubmit. * The Signin was successful. Return undefined. Tanstack Form will know that it was successful and execute the onSubmit To summarize, validators are allowed to mutate data. Their return type simply informs tanstack on whether or not it should continue with the propagation That's assuming that the error is form-related. If it's just any error, you should keep it in onSubmit since the submission was fine.
vicious-gold
vicious-gold4mo ago
I came here for this exact problem. I guess I can completely ignore onSubmit and solely use onSubmitAsync since 99% of my forms require error handling.
xenial-black
xenial-black4mo ago
you can also treat onSubmit as a onSuccess callback in that case, so it still has its uses redirecting to a new page, for example

Did you find this page helpful?