Skip to main content

useForm

useForm is a hook for defining, validating and submitting forms.

Submit feedback
github
import { useForm } from '@uhg-abyss/web/hooks/useForm';

Usage

Default values

The defaultValues prop populates the entire form with default values. It supports both synchronous and asynchronous assignments of default values.

Values

The values props will react to changes and update the form values, which is useful when your form needs to be updated by external state or server data.

// set default value sync
function App({ values }) {
useForm({
values, // will get updated when values props updates
});
}
function App() {
const values = useFetch('/api');
useForm({
defaultValues: {
firstName: '',
lastName: '',
},
values, // will get updated once values returns
});
}

Form state

This object contains information about the form state. If you want to subscribe to formState via useEffect, make sure that you place the entire formState in the optional array.

const form = useForm();
const {
errors, // An object with field errors
isDirty, // Set to true after the user modifies any of the inputs.
isValid, // Set to true if the form doesn't have any errors.
isValidating, // Set to true during validation.
isSubmitting, // true if the form is currently being submitted; false if otherwise.
isSubmitted, // Set to true after the form is submitted.
isSubmitSuccessful, // Indicate the form was successfully submitted without any Promise rejection or Error being thrown within the handleSubmit callback.
submitCount, // Number of times the form was submitted.
touchedFields, // An object containing all the inputs the user has interacted with.
dirtyFields, // An object with the user-modified fields.
} = form.formState;

Watch

This will watch specified inputs and return their values. It is useful for determining what to render.

Handle submit

This function will receive the form data if form validation is successful.

Validate model

This function will receive the model data if form validation is successful.

Reset

Reset either the entire form state or part of the form state.

When invoking reset({ value }) without supplying defaultValues via useForm, the library will replace defaultValues with a shallow clone value object that you provide (not deepClone).

// ❌ avoid the following with deep nested default values
const defaultValues = { object: { deepNest: { file: new File() } } };
useForm({ defaultValues });
reset(defaultValues); // share the same reference
// ✅ it's safer with the following, as we only doing shallow clone with defaultValues
useForm({ deepNest: { file: new File() } });
reset({ deepNest: { file: new File() } });

Set error

The function allows you to manually set one or more errors.

Clear errors

This function can manually clear errors in the form.

Set value

This function allows you to dynamically set the value of a registered field. At the same time, it tries to avoid unnecessary re-renders.

Set focus

This method will allow users to programmatically focus on input. Make sure the input's ref is registered in the hook form.

Get values

An optimized helper for reading form values. The difference between watch and getValues is that getValues will not trigger re-renders or subscribe to input changes.

Trigger

Manually triggers form or input validation. This method is also useful when you have dependent validation (input validation depends on another input's value).

Validation strategy

There are two different validation strategies:

  • mode: Validation strategy before submitting (default: onSubmit).
  • reValidateMode: Validation strategy after submitting (default: onChange).

Teams should only use the following options:

  • mode: onChange | onSubmit
  • reValidateMode: onChange | onSubmit

Disclaimer: Using other validation strategies can lead to inconsistent behavior.

Cross-field validation example

Form input autofill

Autofill off

Additional documentation

@uhg-abyss/web/hooks/useForm is a built on top of the useForm hook from React Form Hook. Teams that already leverage or want to use React Hook Form in other spots in your application can use the @uhg-abyss/web/tools/reactHookFormTools package.

This package can ensure you are using the same version of React Hook Form across your application and can also be used to grab type information directly. Here is an example below:

**Note: ** You should be using Abyss's useForm hook when using Abyss componenets and not react hook forms.

import { SubmitHandler } from '@uhg-abyss/web/tools/reactHookFormTools';
interface FormData {
firstName: string;
}
///...
const handleSubmit: SubmitHandler<FormData> = (data) => {
console.log('data', data);
};
///...

Using TypeScript with useForm gives you strong type checking for your form data structure. Here's a example:

interface FormData {
firstName: string;
lastName: string;
}
const form = useForm<FormData>({
defaultValues: {
firstName: '',
lastName: '',
pizza: 'cheese', // Throws TS error since pizza is not a field in FormData
},
});
// Throws TS error since pizza is not a field in FormData
const WatchField = form.watch('pizza');
// Doesn't throw TS error since firstName and lastName are fields in FormData
const WatchFields = form.watch(['firstName', 'lastName']);
Table of Contents