useField()

useField

This hooks allows to create a form field.

Import

import { useFormFields } from "@formiz/core";

Hook methods

setValue()

Set the value of the field.

const MyField = (props) => {
  const { setValue } = useField(props);
  return <input onChange={(e) => setValue(e.target.value)} />;
};

setValue also accepts a function that takes the previous value as a parameter (like React setState).

setValue((previousValue) => {
  // ...
  // Your logic
  // ...
  return newValue;
});

setIsTouched()

Set the value isTouched of the field.

const MyField = (props) => {
  const { setIsTouched } = useField(props);
 
  setIsTouched(true);
 
  return <input />;
};

externalProcessing.start() & externalProcessing.end()

Allows to notify the field that some processing are done in the background (like retrieving some data).

This will update the isValidating state at the field level and also at the form and step levels.

Notify the start of async processing with externalProcessing.start(). Notify the end of async processing with externalProcessing.end().

const MyField = (props) => {
  const { isValidating, externalProcessing } = useField(props);
 
  useEffect(() => {
    externalProcessing.start();
    getSomeAsyncData().then(() => {
      externalProcessing.end();
    });
  }, [externalProcessing]);
 
  /* ... */
};

Hook values

value

Get the current value of the field, before it has been modified by formatValue.

Will be undefined while the form isn't ready, so the field neither.

const MyField = (props) => {
  const { value } = useField(props);
 
  return <input value={value ?? ""} />;
};

formattedValue

Get the current value of the field, after it has been formated by formatValue (if you used it, will be equal to value instead).

Will be undefined while the form isn't ready, so the field neither.

const MyField = (props) => {
  const { value, formattedValue, setValue } = useField(props);
 
  return (
    <input value={value ?? ""} onChange={e => setValue(e.target.value)}>
  );
}
 
<MyField name="fieldWithFormatValue" formatValue={(value) => `__${value}__`} />
 
/* Differences between value and formattedValue if value is "value"
{
  value: 'value',
  formattedValue: '__value__',
}
*/

id

Return a unique id. This id will be created based on the form id and the field name.

const MyField = (props) => {
  const { id } = useField(props)
 
  return (
    <label htmlFor={id}>...</label>
    <input id={id} />
  )
}

isTouched

Return true if the field has been touched.

const { isTouched } = useField(props);

isValid

Return true if the field is valid.

const { isValid } = useField(props);

isValidating

Return true if the field is running async validations.

const { isValidating } = useField(props);

isDebouncing

Return true if the field is debouncing async validations.

const { isDebouncing } = useField(props);

isPristine

Return true if the field has not been changed.

const { isPristine } = useField(props);

isSubmitted

Return true either if the current step or the form has been submitted.

const { isSubmitted } = useField(props);

shouldDisplayError

Return true if the field should display an error, useful when debugging.

const { shouldDisplayError } = useField(props);

errorMessage

Return the first error message.

const { errorMessage } = useField(props);

errorMessages

Return all error messages.

const { errorMessages } = useField(props);

resetKey

Return the number of time the form has been reset.

const { resetKey } = useField(props);
 
useEffect(() => {
  /* Do a side effect on reset */
}, [resetKey]);

Hook extra values

otherProps

Get the props passed to the component without the Formiz props. Allows you to keep composition by spreading this object in your component.

type MyFieldProps = FieldProps<unknown> & { styles: CSS.Properties };
 
const MyField = <FormattedValue = unknown>(
  props: MyFieldProps<FormattedValue>
) => {
  const { otherProps } = useField(props);
 
  // otherProps type is { styles: CSS.Properties }
 
  return <div {...otherProps}>{/* your field here */}</div>;
};

Field props

name

Required

The name is required to register the field in the form.

<Field name="myFieldName" />

Nested objects

Can use lodash-like dot paths to reference nested values.

<Field name="fieldA" />
<Field name="fieldB" />
<Field name="myGroup.fieldA" />
<Field name="myGroup.fieldB" />
 
/* Form values
{
  fieldA: 'value',
  fieldB: 'value',
  myGroup: {
    fieldA: 'value',
    fieldB: 'value',
  },
}
*/

Arrays

Also allows arrays out of the box. Using lodash-like bracket syntax for name allows you to handle fields in a list.

<Field name="myArray[0]" />
<Field name="myArray[1]" />
<Field name="myArrayOfObjects[0].fieldA" />
<Field name="myArrayOfObjects[0].fieldB" />
<Field name="myArrayOfObjects[1].fieldA" />
<Field name="myArrayOfObjects[1].fieldB" />
 
/* Form values
{
  myArray: ['value', 'value'],
  myArrayOfObjects: [
    { fieldA: 'value', fieldB: 'value' },
    { fieldA: 'value', fieldB: 'value' },
  ],
}
*/

defaultValue

Pass a default value to the field.

<Field name="myFieldName" defaultValue="My initial value" />

formatValue(fieldValue)

Format the value before saving it into the internal state.

<Field name="myFieldName" formatValue={(val) => (val || "").trim()} />

onValueChange(fieldValue)

Function triggered on field value change.

<Field name="myFieldName" onValueChange={(val) => console.log(val)} />

required

Shortcut for isRequired() validation.

<Field name="myFieldName" required="Field is required" />

debounceValidationsAsync

Number of milliseconds for debouncing validations. (default is 100).

<Field name="myFieldName" debounceValidationsAsync={200} />

validations

Add validation rules that the value needs to fulfill for the field to be considered valid.

Accept an array of object with the following keys:

  • handler(value, rawValue): Built in validation rule or custom validation function (must return true if the rule is valid).
    • value references the value of the field.
    • rawValue references the value of the field before any formatting of the data via formatValue.
  • deps: Array of external values used in the rule function (like array of dependencies in useEffect).
  • message: The message if the rule is invalid.
  • checkFalsy: When true (default false) validations will run even on falsy values (including null, undefined, '' and false).
<Field
  name="myFieldName"
  validations={[
    {
      handler: isNotEmptyString(),
      message: "Field can't be empty",
    },
    {
      handler: (value) => value.toLowerCase() !== "john",
      message: "Field can't be john",
    },
    {
      handler: (value) => value !== externalValue,
      deps: [externalValue],
      message: "Field can't be the same as external value",
    },
  ]}
/>

validationsAsync

Async validations allows you to run asynchronous code to validate a field, such as an API call. validationsAsync will only be triggered if all the other validations rules are valid.

Accept an array of object with the following keys:

  • handler(fieldValue): Must return a Promise that return true if the rule is valid.
  • deps: Array of external values used in the rule function (like array of dependencies in useEffect).
  • message: The message if the rule is invalid.
<Field
  name="myFieldName"
  validationsAsync={[
    {
      handler: async (value) => {
        const isAlreadyUsed = await validateUsername(value);
        return isAlreadyUsed;
      },
      message: "Username already used, please select another one.",
    },
  ]}
/>

Field config

Allows to pass default values for useField props.

Available props: "formatValue", "required", "validations", "validationsAsync", "debounceValidationsAsync".

unstable_notifyOnChangePropsExclusions

Awaiting contribution