Simple form validation and values transformation.
npm install react-zod-formSimple form handling with full validation control.
- React Zod Form
- Navigation
- Other approaches
- Install
- npm
- Features
- Usage
- Getting values
- Handling issues
- Field value types
- Transform rules
Read this article to know how to choose your form library.
- React hook form
- Formik
- React-final-form
``bash`
npm i react-zod-form
- Zod
- Field value parser by apparent rules
- Field names helper
_If you're not familiar with Zod, begin with it first._
You start from creating new ZodForm
`ts
import ZodForm from "react-zod-form"
const form = new ZodForm()
`
Then you declare some fields
`ts
import ZodForm from "react-zod-form"
import { z } from "zod"
const form = new ZodForm({
userName: z.string().min(3, "Enter at least 3 chars"),
email: z.string().email("Follow this email format: email@example.com"),
website: z.string().url("Follow this URL format: https://example.com")
})
`
You just created Zod form!
Notice: _It's better to keep zod form in the low level to make sure you're creating ZodForm only once._
---
Now let's create react form component
`tsx
function ExampleForm() {
return (
)
}
export default ExampleForm
`
Combine zod schema and give fields their names (help yourself with fields)
`tsx
import ZodForm from "react-zod-form"
import { z } from "zod"
const form = new ZodForm({
userName: z.string().min(3, "Enter at least 3 chars"),
email: z.string().email("Follow this email format: email@example.com"),
website: z.string().url("Follow this URL format: https://example.com")
})
function ExampleForm() {
return (
export default ExampleForm
`
Now let's get some values on event (i.e. onBlur, onFocus, onChange, onSubmit, ...)
`tsx
import { FormEvent } from "react"
import ZodForm from "react-zod-form"
import { z } from "zod"
const form = new ZodForm({
userName: z.string().min(3, "Enter at least 3 chars"),
email: z.string().email("Follow this email format: email@example.com"),
website: z.string().url("Follow this URL format: https://example.com")
})
function ExampleForm() {
/**
* Triggered on input unfocus.
*/
function onBlur(event: FormEvent
event.preventDefault()
// Tries to return a field that was currently unfocused, otherwise throws error
const field = form.parseCurrentField(event)
console.log(field.name, field.value)
// Tries to return all field values, otherwise throws error
const fields = form.parseAllFields(event)
console.log(fields)
}
return (
export default ExampleForm
`
Wow, now you have your fields just in a few lines of code and it's all concise!
Notice: _There is a safe version of parseAllFields - safeParseAllFields, works just same as in zod._
Let's talk about form interface as you may want your form to be a "standonle module"
`tsx
import { FormEvent } from "react"
import ZodForm from "react-zod-form"
import { z } from "zod"
const form = new ZodForm({
userName: z.string().min(3, "Enter at least 3 chars"),
email: z.string().email("Follow this email format: email@example.com"),
website: z.string().url("Follow this URL format: https://example.com")
})
export type ExampleFormFields = z.infer
interface ExampleFormProps {
onBlur?(value: ExampleFormFields): void
}
function ExampleForm(props: ExampleFormProps) {
/**
* Triggered on input unfocus.
*/
function onBlur(event: FormEvent
event.preventDefault()
// Tries to return a field that was currently unfocused, otherwise throws error
const field = form.parseCurrentField(event)
console.log(field.name, field.value)
// Tries to return all field values, otherwise throws error
const fields = form.parseAllFields(event)
console.log(fields)
}
return (
export default ExampleForm
`
I'll explain you this a bit:
Interface ExampleFormFields represents a value that your output will give, your output is to be methods like onBlur, onFocus, onChange, onSubmit.
Issues are form errors. This is a separate module, so you need to import this along with ZodForm.
Let's take the previous example and start with reporting and clearing error
`tsx
import { FormEvent } from "react"
import ZodForm, { useZodFormIssues } from "react-zod-form"
import { z } from "zod"
const form = new ZodForm({
userName: z.string().min(3, "Enter at least 3 chars"),
email: z.string().email("Follow this email format: email@example.com"),
website: z.string().url("Follow this URL format: https://example.com")
})
export type ExampleFormFields = z.infer
interface ExampleFormProps {
onBlur?(value: ExampleFormFields): void
}
function ExampleForm(props: ExampleFormProps) {
const { reportError, clearError } = useZodFormIssues(form)
/**
* Triggered on input unfocus.
*/
function onBlur(event: FormEvent
event.preventDefault()
// Tries to return all field values, otherwise throws error
const fields = form.parseAllFields(event)
if (fields.success) {
clearError() // You better clear error right after success check
console.log(fields)
} else {
reportError(fields.error)
}
}
return (
export default ExampleForm
`
Now continue with displaying issue message
`tsx
import { FormEvent } from "react"
import ZodForm, { useZodFormIssues } from "react-zod-form"
import { z } from "zod"
const form = new ZodForm({
userName: z.string().min(3, "Enter at least 3 chars"),
email: z.string().email("Follow this email format: email@example.com"),
website: z.string().url("Follow this URL format: https://example.com")
})
export type ExampleFormFields = z.infer
interface ExampleFormProps {
onBlur?(value: ExampleFormFields): void
}
function ExampleForm(props: ExampleFormProps) {
const { reportError, clearError, fieldIssues } = useZodFormIssues(form)
/**
* Triggered on input unfocus.
*/
function onBlur(event: FormEvent
event.preventDefault()
// Tries to return all field values, otherwise throws error
const fields = form.parseAllFields(event)
if (fields.success) {
clearError() // You better clear error right after success check
console.log(fields)
} else {
reportError(fields.error)
}
}
return (
export default ExampleForm
`
Notice: _fieldIssues will have the same keys as your form fields._
---
Let's say all your form fields are valid, but something went wrong on a backend
`tsx
import { FormEvent } from "react"
import ZodForm, { useZodFormIssues } from "react-zod-form"
import { z } from "zod"
const form = new ZodForm({
userName: z.string().min(3, "Enter at least 3 chars"),
email: z.string().email("Follow this email format: email@example.com"),
website: z.string().url("Follow this URL format: https://example.com")
})
export type ExampleFormFields = z.infer
interface ExampleFormProps {
onBlur?(value: ExampleFormFields): void
}
function ExampleForm(props: ExampleFormProps) {
const { reportError, clearError, fieldIssues, addIssue } = useZodFormIssues(form)
/**
* Triggered on input unfocus.
*/
function onBlur(event: FormEvent
event.preventDefault()
// Tries to return all field values, otherwise throws error
const fields = form.parseAllFields(event)
if (fields.success) {
clearError() // You better clear error right after success check
requestBackend(fields.data)
} else {
reportError(fields.error)
}
}
/**
* --- THIS IS EXAMPLE ---
*/
function requestBackend(fields: ExampleFormFields) {
const response = send(fields)
if (!response.error) return
response.error.fields.forEach(field => {
addIssue([field.name], field.message)
})
}
return (
export default ExampleForm
`
A form field value may be one of these type (can be in array):
- stringnumber
- boolean
- File
-
Take a look at the interface to understand it better
`ts`
type FormFieldValue = FormFieldValueBasic | FormFieldValueBasic[]
type FormFieldValueBasic = string | number | boolean | File
| Type | Output | Description |
| :-----------------------: | :--------------: | --------------------------------------------------------------------------------------------------------- |
| any | number | If value is a parsable number, it will be converted to number. |any
| | boolean | If value is "true" or "false", it will be converted to boolean. |"radio"
| \| "checkbox" | boolean | If value is "ok" and type is "radio" \| "checkbox", the value from checked attribute will be taken. |"file"
| | File \| File[] | If type is "file", it will give File or File[], depending on multiple` attribute. |