Wit Form

useFormContext

useFormContext lets any component inside the form read and change it from code, even if the component isn't a field. Use it for buttons like "Use my saved address", lookups that fill in other fields, or reading values in an event handler.

import { useFormContext } from 'wit-form';

const form = useFormContext({ formId });

Calling useFormContext doesn't subscribe to any values, so it never makes your component re-render.

function UseSavedAddress() {
  const { setFieldValues } = useFormContext();
  return (
    <button
      type="button"
      onClick={() =>
        setFieldValues([
          { name: 'address.street', value: '1 Main St' },
          { name: 'address.city', value: 'Springfield' },
        ])
      }
    >
      Use saved address
    </button>
  );
}

See the Imperative Updates example.

Options

formId

Type: string · Default: the surrounding form

Only for using a form from outside its provider. See FormProvider.

Returns

Several functions take a field key that says which field you mean:

// A top-level field: a string, or an object
'email'
{ name: 'email', type: 'field' }

// A field inside a field array row
{ name: 'qty', type: 'field', ancestors: [{ name: 'items', rowId }] }

// A whole field array
{ name: 'items', type: 'field-array' }

setValue

Type: (key: string | IFormContextFieldInput, update: { value?: any; extraInfo?: any }) => void

Sets one field's value and/or extra info. Anything you leave out of update stays as it is. If the field is rendered, it re-validates.

setValue('email', { value: 'ada@example.com' });
setValue('country', { value: 'FR', extraInfo: { label: 'France' } });
setValue(
  { name: 'qty', type: 'field', ancestors: [{ name: 'items', rowId }] },
  { value: 3 }
);

With a field array key, value is the new list of rows. It replaces the whole list:

setValue(
  { name: 'items', type: 'field-array' },
  { value: [{ product: 'Ink' }] }
);
  • undefined means "leave unchanged", so you can't set a value to undefined. Use '' or null to clear a field.
  • Setting a field that isn't rendered stores the value. It's included in the submitted values and is used when the field mounts.
  • Setting a value doesn't mark the field as touched, so a new error only appears after a blur or submit.

setFieldValues

Type: (fields: { name: string; value: any; extraInfo?: any; ancestors?: Ancestor[] }[]) => void

Sets several fields in one call. Each entry works like setValue. It's for plain fields only. To replace a field array, use setValue with a field array key.

getValue

Type: (key: IFormContextFieldInput) => { value: any; extraInfo: any } | null

Reads one field, or one field array, right now. Unlike the watch hooks, it doesn't subscribe or cause re-renders, so it's the right choice in event handlers.

const email = getValue({ name: 'email', type: 'field' })?.value;
const rows = getValue({ name: 'items', type: 'field-array' })?.value;

For a top-level field that hasn't mounted yet, it returns the field's initial value.

getValues

Type: () => { values: any; extraInfos: any }

Reads all values and extra infos right now, without subscribing.

getValuesAndExtraInfo

Type: () => { values: any; extraInfos: any }

The same as getValues.

checkIsDirty

Type: (options?: { preCompareUpdateFormValues?: (values) => any }) => boolean

Returns whether the values differ from the initial values, right now. The event-handler version of useIsDirty, with the same option.

if (checkIsDirty() && !confirm('Discard your changes?')) return;

removeFields

Type: (params: { fieldNames: (string | { name: string; ancestors?: Ancestor[] })[] }) => void

Resets the given fields, discarding their current values. Each field goes back to its initial value, or becomes empty if it has none. After a successful submit, the initial values are the submitted ones. To empty a field no matter what, use setValue(name, { value: '' }).

resetInitialValues

Type: (values?: any, extraInfos?: any) => void

Replaces the initial values and resets every field to them. Same as useForm's resetInitialValues.

validateAllFields

Type: () => IFieldError[]

Validates every mounted field and field array and returns the errors. Same as useForm's validateAllFields.

validateAllFieldsAsync

Type: () => Promise<IFieldError[]>

Like validateAllFields, but waits for async validators.

setError, clearErrors, setFormErrors, setFocus

The same as in useForm, for components that aren't where useForm is called. For example, a field component can show a server error, or a button can clear errors.

const { setError } = useFormContext();
setError('email', 'This email is already registered');

To read the form's state (isValid, isSubmitting, errors, ...) from any component, use useFormState.

On this page