T
TanStack8mo ago
rising-crimson

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
rising-crimson
rising-crimsonOP8mo 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>
)}
/>
jolly-crimson
jolly-crimson8mo 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.
rare-sapphire
rare-sapphire7mo 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.
jolly-crimson
jolly-crimson7mo 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?