Skip to content

useField

Reactive field state with validation, designed for use with GTInput.

Usage

tsx
import { useField } from '@grundtone/react-native';
import { required, email } from '@grundtone/react-native';

function EmailForm() {
  const field = useField({
    validators: [required(), email()],
    validateOn: 'blur',
  });

  return (
    <GTInput
      {...field.fieldProps}
      errorText={field.errorText}
      label="Email"
      type="email"
    />
  );
}

Options

OptionTypeDefaultDescription
validatorsValidator[][]Array of validator functions from @grundtone/utils
validateOn'input' | 'blur' | 'submit''blur'When to run validation
initialValuestring''Starting value

Return value

PropertyTypeDescription
valuestringThe current field value
setValue(v: string) => voidUpdate the value
errorTextstring | undefinedError message (shown only after touched)
touchedbooleanWhether the field has been interacted with
isValidbooleanWhether the current value passes all validators
validate()() => ValidationResultManually trigger validation
reset()() => voidReset to initial state
fieldPropsobjectProps to spread on GTInput (value, onChangeText, onBlur)

Validation modes

  • blur (default) — Validates when the field loses focus.
  • input — Validates on every keystroke.
  • submit — Only validates when validate() is called manually.

Available validators

Import from @grundtone/react-native (or @grundtone/utils):

FactoryDescription
required(msg?)Non-empty after trim
email(msg?)Valid email format
phone(msg?)Danish phone number (8 digits)
cpr(msg?)Danish CPR number
cvr(msg?)Danish CVR number (modulus 11)
minLength(n, msg?)Minimum character length
maxLength(n, msg?)Maximum character length
pattern(regex, msg?)Custom regex match
url(msg?)Valid HTTP(S) URL
composeValidators(...v)Compose multiple validators into one

All validators (except required) pass on empty strings, so they're optional by default. Combine with required() to make a field mandatory.

Custom validators

A validator is just a function (value: string) => ValidationResult:

ts
import type { Validator } from '@grundtone/react-native';

const noSpaces: Validator = (value) =>
  value.includes(' ')
    ? { isValid: false, message: 'No spaces allowed' }
    : { isValid: true };

const field = useField({ validators: [required(), noSpaces] });