Tanstack Form with Next.JS App Router
Apr 19, 2024
0
Forms are the most important part of any web application. It is used to collect data from the user. It can be tricky to handle form with good validation, accessibility and custom styling. Providing good user experience is the most important part of any web application. You don't want to let user fill the form again and again.
Tanstack Form is a best tool for handling form in our React Apps which provides Reactive, Complex validation, Accessibility and custom styling. Which help to build a better and robust form in our Apps. It works with React Server Component out of the box and Support for Typescript make it end to end type safe.
Tanstack From
- Reactive : Tanstack Form is reactive in nature. It means that the form will update automatically when the state of the form changes. It uses the concept of observables to achieve this.
- Complex validation : Tanstack Form provides a easy way to validate the form. we can use the own custom validation logic or use the built-in supported validators like zod, yup, valibot etc.
- Bundle size : Tanstack Form is very lightweight. It is only 6.1kb. Compared to React Hook Form which is 10.1kb and Formik which is 13.2kb.
- Type safe : Tanstack Form is fully type safe. It provides full type safety with Typescript. It even infer the type of nested objects and arrays quite well.
Installation#
We are going to use Tanstack Form with Next.JS latest version where we will explore how we can use Tanstack Form with Next.JS App Router using server action.
I assume you have already created a Next.JS App and you are familiar with Next.JS App Router.
We will use zod as a validation library. You can use any other validation library like yup, valibot etc which are supported by Tanstack Form.
Tanstack form setup#
We have to structure our form in a way that it can work with server component and we can use server action.
Form Schema
Tanstack Form provides formOptions
function which let us create default values which we can share to client and server actions both places. We can create form schema and validation for server using createServerValidate
.
Here we have created a form schema with default values and validation logic. We are using onServerValidate
function to validate the form on server side. We are returning the error message if the validation fails.
You can use ZOD to validte data instead for manually checking the validation.
Server Action
We need to create a server action which will be used to validate the form on server side and do the server side action like saving the form data to database etc.
Here witch formAction
function we are validating the form data and doing the server side action. We are using serverValidate
function to validate the form data.
We are extracting the form data from formData
as formData contains some extra data which we don't need. We are using getFormData
function to extract the form data.
Server Action in Client and Server Component in Next.Js Explained
Server Actions are asynchronous functions that are executed on the server. They can be used in Server and Client Components to handle form submissions and data mutations in Next.js applications.
Read Full PostForm Component
With the above setup we are ready to use Tanstack Form with server action. Now we need to create a form component which will be used to render the form.
Let's break down the above code:
useActionState
is hook provided by React which lets us work with server actions forms. It allows us to update state based on the result of a form action.We are using
useForm
hook to get the form instance. where we are passing our default values and usinguseTransform
function to merge the form state with the server state.We are extracting the server side errors from
formErrors
and showing them in the form. If you remember we are passing error from server in a form that later we can transform it in key value pair and use it.We are rendering our form and there is no client side validation yet.
action
let us use server action andonSubmit
for client side interaction with form to show state based on event and validation.ErrorText
Component is where we are showing error for client and server both. In the form of children we are passing the server error and in prop the client one.
You see we are using ButtonStatus
component which let's us know the current state of form.
You must be thinking why we created a different component as we can hove use in the same component right?
Well to work useFormStatus
we must need to use in a component which will be rendered inside the form. and its provides state for parent form. Like here we are using pending
and its provides few other state too you can check here
Client side validation using ZOD#
Zod is a TypeScript-first schema declaration and validation library. I like zod because it is very easy to use and provides a lot of features an widely used in the community, Which make it easy to find the solution if you face any issue.
Here we are using zodValidator
which is provided by @tanstack/zod-form-adapter
. We are using zod
to validate the form on client side. We are using validators
prop to validate the form fields. We are using onChange
validator to validate the form fields on change.
You can write any custom validation logic in the validators
prop. It just you have return support error types like string, boolean, null etc.
The source code for this article is available on GitHub
Conclusion#
Tanstack Form is a best tool for handling form in our React Apps and with the rise of RSC(React Server Components), We want to use server action which make life easy to handle form on server side. The end to end type safe with Typescript make it more reliable and easy to use.
The flexibility and control it provides to the developer is amazing. We always want to build a better and robust form in our Apps which provide good user experience. There are many other things to learn which you can explore in the official documentation.
I hope you like this article, If you have any question or suggestion, feel free to ask me in the comment section below. Happy coding😊
Comments (1)