Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supporting async validation in createServerValidate #855

Merged

Conversation

ogawa0071
Copy link
Contributor

Changes

Currently, server-side validation cannot be performed asynchronously. This is particularly inconvenient when using external validation adapters like Zod to check database values against form inputs.

Client-side validation can already be performed asynchronously, and since server-side operations are generally expected to be asynchronous, the impact of this change should be minimal.

  • Change validatorAdapter().validate() to validatorAdapter().validateAsync()
  • Fixed onServerValidate property is not supported for validatorAdapter (Ex. Zod) TypeScirpt types

Sample Code

"use server";

import {
  ServerValidateError,
  createServerValidate,
} from "@tanstack/react-form/nextjs";
import { zodValidator } from "@tanstack/zod-form-adapter";
import { redirect } from "next/navigation";
import { z } from "zod";

const serverSchema = schema.extend({
  firstName: z
    .string()
    .min(8, {
      message: "Server: First Name must be at least 8 characters.",
    })
    .refine(async () => {
      // In the actual implementation, queries to the database will be performed here.
      console.log("Server: Validate First Name...");
      await new Promise((resolve) => setTimeout(resolve, 1000));
      return true;
    }),
});

const serverValidate = createServerValidate({
  validatorAdapter: zodValidator(),
  // TypeScript error on following line
  onServerValidate: serverSchema,
});

export default async function someAction(prev: unknown, formData: FormData) {
  try {
    await serverValidate(formData);
  } catch (e) {
    if (e instanceof ServerValidateError) {
      return e.formState;
    }

    // Some other error occurred while validating your form
    throw e;
  }

  // Your form has successfully validated!
  console.log(formData.get("firstName"));

  redirect("/");
}

@ogawa0071
Copy link
Contributor Author

TypeScript type implementation was referenced from the following code:

/**
* @private
*/
export type FormValidateAsyncFn<
TFormData,
TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,
> = (props: {
value: TFormData
formApi: FormApi<TFormData, TFormValidator>
signal: AbortSignal
}) => ValidationError | Promise<ValidationError>
/**
* @private
*/
export type FormAsyncValidateOrFn<
TFormData,
TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,
> = TFormValidator extends Validator<TFormData, infer FFN>
? FFN | FormValidateAsyncFn<TFormData, TFormValidator>
: FormValidateAsyncFn<TFormData, TFormValidator>

@Balastrong
Copy link
Member

Thanks for the PR! Looks good so far but let's doublecheck, have you tested also with validator adapters like zod? Could you also write some unit tests for that?

@ogawa0071
Copy link
Contributor Author

@Balastrong
Thank you for your feedback!

  • I have updated the branch to follow the latest main and added tests for the zod-form-adapter. Please review them.
  • There are type tests for the FormApi in the zod-form-adapter. Do you think type tests for createServerValidate are necessary?
  • I haven’t added tests for Valibot and yup yet. Are these required? Also, there are no existing tests for createServerValidate within react-form itself. Should I add them as well?

Looking forward to your guidance!

Copy link
Member

@Balastrong Balastrong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR is already ok, if you want to add more tests for valibot and yup it'd be great!

Tests on types are also welcome, up to you if you want to make them on this branch or on a new PR later.

Thank you!

@ogawa0071
Copy link
Contributor Author

@Balastrong
I don't have time to act on it right now so I won't be adding any new tests in this PR.
Thanks for checking.

@Balastrong
Copy link
Member

I'll take care of that and merge then, thanks! :)

Copy link

nx-cloud bot commented Aug 27, 2024

☁️ Nx Cloud Report

CI is running/has finished running commands for commit 606e988. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this CI Pipeline Execution


✅ Successfully ran 2 targets

Sent with 💌 from NxCloud.

Copy link

pkg-pr-new bot commented Aug 27, 2024

commit: 606e988

@tanstack/angular-form

pnpm add https://pkg.pr.new/@tanstack/angular-form@855

@tanstack/form-core

pnpm add https://pkg.pr.new/@tanstack/form-core@855

@tanstack/lit-form

pnpm add https://pkg.pr.new/@tanstack/lit-form@855

@tanstack/react-form

pnpm add https://pkg.pr.new/@tanstack/react-form@855

@tanstack/solid-form

pnpm add https://pkg.pr.new/@tanstack/solid-form@855

@tanstack/valibot-form-adapter

pnpm add https://pkg.pr.new/@tanstack/valibot-form-adapter@855

@tanstack/vue-form

pnpm add https://pkg.pr.new/@tanstack/vue-form@855

@tanstack/yup-form-adapter

pnpm add https://pkg.pr.new/@tanstack/yup-form-adapter@855

@tanstack/zod-form-adapter

pnpm add https://pkg.pr.new/@tanstack/zod-form-adapter@855

Open in Stackblitz

More templates

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants