Forms
/ API Reference
Forms
/ API Reference

useField

A React hook for managing a single form field.
It uses useState (new tab) under the hood and leverages Zod (new tab) for validation.

The Gist

'use client'
import { z } from 'zod'
import { useField } from '@weser/forms'

const schema = z.string().min(3, 'Please enter at least 3 characters')

export default function NameField() {
  const field = useField(schema, { name: 'name', value: '' })

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    // mark as touched to show errors
    field.update({ touched: true })
    if (field.validate().success) {
      // submit
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input {...field.inputProps} placeholder="Your name" />
      {field.errorMessage && <p role="alert">{field.errorMessage}</p>}
      <button>Save</button>
    </form>
  )
}

Parameters

ParameterTypeDescription
schemaZodTypeThe Zod schema used to validate the value.
optionsOptionsInitial field data and additional configuration options.

Options

PropertyTypeDefaultDescription
valueT = string''Initial value
disabledbooleanfalseInitial disabled state
touchedbooleanfalseInitial touched state that indicates whether validation errors are shown or not
namestringThe name of the field
showValidationOn"change" | "blur" | "submit""submit"Which event is used to trigger the touched state
parseValue(e: Event) => any(e) => e.target.valueHow the value is received from the input element.
Use e.target.checked when working with <input type="checkbox" />
formatErrorMessage(error: ZodIssue, value: any, name?: string) => string(error) => error.messageA function to overwrite the default error message from Zod. Receives the Zod issue, the current value and the name of the field.

formatErrorMessage

By default, the error message from Zod is used. While those are better than nothing, we still often want to show custom error messages to the user. This is also helpful when supporting multiple languages and having to translate on the fly on when your schemas are shared between multiple applications.

import { ZodIssue } from 'zod'

// Note: the type is ZodIssue and not ZodError
function formatErrorMessage(error: ZodIssue, value: any, name: string) {
  switch (error.code) {
    case 'too_small':
      return `This field ${name} requires at least ${error.minimum} characters.`
    default:
      return error.message
  }
}

Returns

(Object) An object with the following properties and methods:

value

The current value of the field.

disabled

Whether the field is disabled.

touched

Whether the field is touched.

dirty

Whether the field is dirty.

valid

Whether the field is valid.

errorMessage

A string containing the validation message.
Only returned if the field is invalid and touched.

update

A function that takes field input data and updates the field accordingly.
Useful e.g. when receiving data from an API.

Re-validation

If the value is changed, it will automatically trigger re-validation.


Remember, error messages are only shown if the field is touched.

Example

update({
  value: 'Foo',
  touched: true,
})

validate

A function that validates the field.

Returns

(ZodSafeParseResult) Returns an object with success and error properties.

PropertyTypeDescription
successbooleanWhether the validation was successful.
errorZodErrorThe error object if the validation was not successful.

reset

A function that resets the field back to its initial state.

inputProps

An object with properties that can be passed to native HTML input, select and textarea elements.
Use data-valid to style the element based on the validation state.

PropertyTypeDescription
namestringThe name of the field
valueanyThe value of the field
disabledbooleanWhether the field is disabled
data-validbooleanWhether the field is valid
onChangeReact.ChangeEventHandlerThe onChange event handler
onFocusReact.KeyboardEventHandlerThe onFocus event handler
onBlurReact.KeyboardEventHandlerThe onBlur event handler

props

An alternative to inputProps, that can be used to create custom components that render label and input elements. Also includes errorMessage and valid for proper error-state handling.

PropertyTypeDescription
valueanyThe value of the field
validbooleanWhether the field is valid
requiredbooleanWhether the field is required
disabledbooleanWhether the field is disabled
errorMessagestringThe error message
namestringThe name of the field
onChangeReact.ChangeEventHandlerThe onChange event handler
onFocusReact.KeyboardEventHandlerThe onFocus event handler
onBlurReact.KeyboardEventHandlerThe onBlur event handler

Generic Type

By default, useField expects string values and defaults to an empty string if no initial value is provided.
In order to also support e.g. boolean values or arrays, we can customise the generic types and pass new values.

Important Note

When using a custom type, the default value becomes mandatory or else it will default to an empty string.

import { ChangeEvent } from 'react'

const acceptsTerms = useField<boolean, ChangeEvent<HTMLInputElement>>(
  z.boolean(),
  {
    parseValue: (e) => e.target.checked,
    value: false,
  }
)

type ArrayChangeEvent = (value: Array<string>) => void
const tags = useField<Array<string>, ArrayChangeEvent>(z.array(z.string()), {
  // overwrite the default that expects a native HTML event
  parseValue: (value) => value,
  value: [],
})

Passing a custom value type and change event will also change the type of field.value and the expected input for update.

On this page