Skip to content

Instantly share code, notes, and snippets.

@Joeldorne
Created June 28, 2024 12:35
Show Gist options
  • Select an option

  • Save Joeldorne/ab1419c4c4d35bc9e794b81ade0e7a62 to your computer and use it in GitHub Desktop.

Select an option

Save Joeldorne/ab1419c4c4d35bc9e794b81ade0e7a62 to your computer and use it in GitHub Desktop.
Client Side Component - TanStack Form
"use client"
import { useForm } from "@tanstack/react-form"
import { zodValidator } from "@tanstack/zod-form-adapter"
import { z } from "zod"
import { submitForm } from "./actions" // Make sure to create this file with the server action
import { useState } from "react"
const formSchema = z.object({
name: z.string().min(2, "Name must be at least 2 characters"),
email: z.string().email("Invalid email address"),
})
type FormValues = z.infer<typeof formSchema>
export default function MyForm() {
const [serverResponse, setServerResponse] = useState<{ error?: string; success?: boolean; message?: string }>({})
const form = useForm<FormValues>({
defaultValues: {
name: "",
email: "",
},
onSubmit: async (values) => {
try {
const result = await submitForm(values)
setServerResponse(result)
} catch (error) {
setServerResponse({ error: error.message })
}
},
validatorAdapter: zodValidator,
})
return (
<form.Provider>
<form
onSubmit={(e) => {
e.preventDefault()
e.stopPropagation()
form.handleSubmit()
}}
className="space-y-4"
>
<div>
<label htmlFor="name" className="block text-sm font-medium text-gray-700">Name:</label>
<form.Field
name="name"
validators={{ onChange: formSchema.shape.name }}
>
{(field) => (
<div>
<input
id="name"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
/>
{field.state.meta.touchedErrors ? (
<em className="text-red-500 text-sm">{field.state.meta.touchedErrors}</em>
) : null}
</div>
)}
</form.Field>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700">Email:</label>
<form.Field
name="email"
validators={{ onChange: formSchema.shape.email }}
>
{(field) => (
<div>
<input
id="email"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
/>
{field.state.meta.touchedErrors ? (
<em className="text-red-500 text-sm">{field.state.meta.touchedErrors}</em>
) : null}
</div>
)}
</form.Field>
</div>
<button
type="submit"
className="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Submit
</button>
{serverResponse.error && (
<p className="mt-2 text-sm text-red-600">Error: {serverResponse.error}</p>
)}
{serverResponse.success && (
<p className="mt-2 text-sm text-green-600">{serverResponse.message}</p>
)}
</form>
</form.Provider>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment