Skip to main content

useForm

This is a custom React hook that helps you with building forms. It takes config parameters and returns useful methods as follows.

const methods = useForm(config);

Config#

An object with the following options:

id#

string

The ID of the hook, it's used to pair with the related hook(s) of React Cool Form. We only need it when using multiple form hooks at the same time.

defaultValues#

Record<string, any>

Default field values of the form. In most case (especially working with TypeScript), we should use it to initialize a field's value and use the defaultValue/defaultChecked attribute for the case of conditional fields. The defaultValues also used to compare against the current values to calculate isDirty and dirty.

  • The defaultValues is cached at the first render within the custom hook. If you want to reset it or lazily set it, you can use the reset method.

excludeFields#

string[]

Tell React Cool Form to exclude field(s) by passing in the name/id/class of the field. You can also exclude a field via the pre-defined data-rcf-exclude attribute.

  • The excludeFields and data-rcf-exclude won't affect the functionality of the useControlled.
const App = () => {  const { form } = useForm({    excludeFields: ["foo", "#bar", ".baz"],  });
  return (    <form ref={form}>      <input name="foo" />      <input id="bar" />      <input className="baz" />      {/* Excluding via the pre-defined data attribute */}      <input data-rcf-exclude />    </form>  );};

๐Ÿ‘‰๐Ÿป See the Exclude Fields to learn more.

builtInValidationMode#

"message" | "state" | false

We can configure the mode of the built-in validation as follows:

  • "message" (default): Returns a localized message that describes the validation constraints that the field does not satisfy (if any)
  • "state": Returns the key of the invalid property (e.g. "valueMissing", "tooShort", etc.) of the ValidityState (if any)
  • false: Disable the built-in validation

validateOnChange#

boolean

Tell React Cool Form to run validations on change events as well as the setValue method. Default is true.

validateOnBlur#

boolean

Tell React Cool Form to run validations on blur events. Default is true.

focusOnError#

boolean | string[] | (names: string[]) => string[]

Tell React Cool Form to apply focus to the first field with an error upon an attempted form submission. Default is true.

  • Only native input elements that support HTMLElement.focus() will work.
  • The focus order is based on the field order (i.e. top-to-bottom and left-to-right).
// Current fields: { foo: "", bar: "", baz: "" }
// Disable this featureconst methods = useForm({ focusOnError: false });
// Change the focus order by passing in field namesconst methods = useForm({ focusOnError: ["bar", "foo", "baz"] });
// Change the focus order by modifying existing field namesconst methods = useForm({  focusOnError: (names) => {    [names[0], names[1]] = [names[1], names[0]];    return names;  },});

removeOnUnmounted#

boolean | string[] | (names: string[]) => string[]

By default, React Cool Form automatically removes the related state (i.e. value, error, touched, dirty) and default value of an unmounted field for us. However, we can set the removeOnUnmounted to false to maintain all the data or give it field names to maintain partial data. Default is true.

  • To keep a default value existing between a dynamically show/hide field, we can set it via defaultValue attribute or option.
  • If this feature doesn't meet your needs, you can use the removeField to control what data that you want to remove instead.
// Current values: { foo: "๐ŸŽ", bar: "๐Ÿ‹", baz: "๐Ÿฅ" }
// Keep all the dataconst methods = useForm({ removeOnUnmounted: false });
// Keep partial data (i.e. "bar" and "baz") by passing in field namesconst methods = useForm({ removeOnUnmounted: ["foo"] });
// Keep partial data (i.e. "bar" and "baz") by modifying existing field namesconst methods = useForm({  removeOnUnmounted: (names) => names.filter((name) => name === "foo"),});

๐Ÿ‘‰๐Ÿป See the conditional fields example to learn more.

validate#

(values: FormValues) => FormErrors | false | void | Promise<FormErrors | false | void>

A synchronous/asynchronous function that is used for the form-level validation. It takes all the form's values and returns any validation errors (or returns undefined if there's no error). The validation errors must be in the same shape as the values of the form.

onSubmit#

(values: FormValues, options: Object, e?: Event) => void | Promise<void>

The form submission handler will be called when the form is submitted (or when the submit method is called) and validated successfully. It takes the following parameters:

const methods = useForm({  onSubmit: async (    values,    {      getState,      setValue,      setTouched,      setDirty,      setError,      focus,      runValidation,      removeField,      submit,      reset,    },    e  ) => {    /* Do something... */  },});

๐Ÿ‘‰๐Ÿป See the Form Submission to learn more.

onError#

(errors: FormErrors, options: Object, e?: Event) => void

The form error handler that is called when the form is submitted (or when the submit method is called) and validated failed. It takes the following parameters:

const methods = useForm({  onError: (    errors,    {      getState,      setValue,      setTouched,      setDirty,      setError,      focus,      runValidation,      removeField,      submit,      reset,    },    e  ) => {    /* Do something... */  },});

๐Ÿ‘‰๐Ÿป See the Form Submission to learn more.

onReset#

(values: FormValues, options: Object, e?: Event) => void

The form reset handler that is called when the form is reset (or when the reset method is called). It takes the following parameters:

const methods = useForm({  onReset: (    values,    {      getState,      setValue,      setTouched,      setDirty,      setError,      focus,      runValidation,      removeField,      submit,      reset,    },    e  ) => {    /* Do something... */  },});

๐Ÿ‘‰๐Ÿป See the Reset Form to learn more.

onStateChange#

(formState: FormState) => void

The form state change handler that is called on every state change. It's useful for debugging or triggering a handler.

  • Want to trigger a handler based on certain properties in the form state? Check out the useFormState to learn more.
  • formState is readonly and should not be mutated directly.
const methods = useForm({  onStateChange: (formState) => console.log("State: ", formState),});

Methods#

An object with the following methods:

form#

(element: HTMLElement) => void

This method allows us to integrate an existing form or a container where inputs are used with React Cool Form.

field#

(validateOrOptions: Function | Object) => Function

This method allows us to do field-level validation and data type conversion via the ref attribute. For the data type conversion, React Cool Form supports the valueAsNumber, valueAsDate, and custom parser.

  • For your convenience, the values of <input type="number"> and <input type="radio"> are converted to number by default.
  • When using this method with the useControlled, the functionality of the method will be replaced.
const { field } = useForm();
<input  name="foo"  type="date"  ref={field({    validate: (value, values /* Form values */) => !value.length && "Required",    valueAsNumber: true, // (Default = false) Returns a number representing the field's value if applicable, otherwise, returns "NaN"    valueAsDate: true, // (Default = false) Returns a Date object representing the field's value if applicable, otherwise, returns "null"    parse: (value) => customParser(value), // Returns whatever value you want through the callback  })}/>;

If you just want to validate the field, there's a shortcut for it:

<input nam="foo" ref={field((value) => !value.length && "Required")} />

focus#

(name: string, delay?: number) => void

This method allows us to apply focus to a field. If you want to focus on the first field of a nested fields, you can just pass in the parent path as below.

note

When working with Arrays and Lists, we need to set delay (delay = 0 is acceptable) to wait for a field rendered before applying focus to it.

const App = () => {  const { form, focus } = useForm();
  useEffect(() => {    // Will focuses on the first field after 0.5 second    // It works the same as `focus("foo.a", 500)`    focus("foo", 500);  }, []);
  return (    <form ref={form}>      <input name="foo.a" />      <input name="foo.b" />      <input name="foo.c" />      <input type="submit" />    </form>  );};

๐Ÿ‘‰๐Ÿป See the Applying Focus to learn more.

use#

(path: string | string[] | Record<string, string>, options?: Object) => any

This method provides us a performant way to use the form state with minimized re-renders. See the Form State to learn more.

getState#

(path?: string | string[] | Record<string, string>) => any

This method allows us to read the form state without triggering re-renders. See the Reading the State to learn more.

setValue#

(name: string, value: any | Function, options?: Object) => void

This method allows us to manually set/clear the value of a field. Useful for creating custom field change handlers.

const { setValue } = useForm();
setValue("fieldName", "value", {  shouldValidate: true, // (Default = "validateOnChange" option) Triggers field validation  shouldTouched: true, // (Default = true) Sets the field as touched  shouldDirty: true, // (Default = true) Sets the field as dirty});
// We can also pass a callback as the "value" parameter, similar to React's setState callback stylesetValue("fieldName", (prevValue) => prevValue.splice(2, 0, "๐ŸŽ"));

We can clear the value of a field by the following way:

setValue("fieldName", undefined); // The field will be unset: { fieldName: "value" } โ†’ {}

setTouched#

(name: string, isTouched?: boolean, options?: Object) => void

This method allows us to manually set/clear the touched of a field. Useful for creating custom field touched handlers.

const { setTouched } = useForm();
// Common use casesetTouched("fieldName");
// Full parameterssetTouched(  "fieldName",  true, // (Default = true) Sets the field as touched  {    shouldValidate: true, // (Default = "validateOnBlur" option) Triggers field validation  });

We can clear the touched of a field by the following way:

setTouched("fieldName", false); // The touched will be unset: { fieldName: true } โ†’ {}

setDirty#

(name: string, isDirty?: boolean) => void

This method allows us to manually set/clear the dirty of a field. Useful for creating custom field dirty handlers.

const { setDirty } = useForm();
// Common use casesetDirty("fieldName");

We can clear the dirty of a field by the following way:

setDirty("fieldName", false); // The dirty will be unset: { fieldName: true } โ†’ {}

setError#

(name: string, error: any | Function) => void

This method allows us to manually set/clear the error of a field. Useful for creating custom field error handlers.

const { setError } = useForm();
setError("fieldName", "Required");
// We can also pass a callback as the "error" parameter, similar to React's setState callback stylesetError("fieldName", (prevError) => (prevError ? "Too short" : "Required"));

We can clear the error of a field by the following way (or using clearErrors):

setError("fieldName", undefined); // Or any falsy values, the error will be unset: { fieldName: "Required" } โ†’ {}

clearErrors#

(name?: string | string[]) => void

This method allows us to manually clear errors (or an error). Useful for creating custom field error handlers.

const { clearErrors } = useForm();
// Current errors: { foo: { bar: "Required", baz: "Required" }, qux: "Required" }
clearErrors(); // Clears all errors. Result: {}
clearErrors("foo"); // Clears both "foo.bar" and "foo.baz". Result: { qux: "Required" }
clearErrors(["foo.bar", "foo.baz"]); // Clears "foo.bar" and "foo.baz" respectively. Result: { foo: {}, qux: "Required" }

runValidation#

(name?: string | string[], options?: Object) => Promise<boolean>

This method allows us to manually run validation for the form or field(s).

  • It returns a boolean that indicates the validation results, true means valid, false otherwise.
  • Please note, when enabling the Filter Untouched Field Errors, only the errors of the touched fields are accessible.
const { runValidation } = useForm();
// Validates the form (i.e. all the fields)runValidation();
// Validates single fieldrunValidation("fieldName");
// Validates multiple fieldsrunValidation(["fieldName1", "fieldName2"]);
// With resultconst validateForm = async () => {  const isValid = await runValidation();  console.log("The form is: ", isValid ? "valid" : "invalid");};
// Full parametersrunValidation("fieldName", {  shouldFocus: true, // (Default = "focusOnError" option) To focus to the first field with an error within the specified fields});

๐Ÿ‘‰๐Ÿป See the Validation Guide to learn more.

removeField#

(name: string, exclude?: string[]) => void

This method allows us to manually remove the related state (i.e. value, error, touched, dirty) and default value of a field, it also excludes a field from the form.

  • By default, React Cool Form automatically removes an unmounted field for us but this method gives us the ability to control what data that we want to remove.
const App = () => {  const [show, setShow] = useState(true);  const { form, removeField } = useForm({    removeOnUnmounted: false, // Disable the feature of automatically removing fields  });
  const handleToggle = () => {    setShow(!show);    // We can exclude these data: ["defaultValue", "value", "error", "touched", "dirty"]    if (!show) removeField("foo", ["defaultValue"]); // Keep the default value  };
  return (    <form ref={form}>      <input type="checkbox" onChange={handleToggle} data-rcf-exclude />      {show && <input name="foo" />}      {/* Other fields... */}    </form>  );};

submit#

(e?: Event) => Promise<Result>

This method allows us to manually submit the form, it returns a promise with the following results. Useful for meeting the needs of custom design.

  • Returns a promise with errors when any validation errors
  • Returns a promise with values when the form is validated successfully
const { submit } = useForm({  onSubmit: (values, options, e) => console.log("onSubmit: ", values), // Triggered on form submit + valid  onError: (errors, options, e) => console.log("onError: ", errors), // Triggered on form submit + invalid});
const handleFormSubmit = async (e) => {  const { errors, values } = await submit(e); // Pass the event object to the event handlers
  if (errors) {    // Do something for invalid case  } else {    // Do something for valid case  }};

๐Ÿ‘‰๐Ÿป See the Form Submission to learn more.

reset#

(values?: FormValues | Function | null, exclude?: string[] | null, e?: Event) => void

This method allows us to manually reset the form. It will restore the form to its default values as well as reset/clear all the related state.

  • We can pass values as an optional parameter to update the default values.
  • We can pass exclude as an optional parameter to prevent specific state from reset.
const { reset } = useForm({  defaultValues: { firstName: "", lastName: "" },  onReset: (values, options, e) => console.log("onReset: ", values), // Triggered on form reset});
const handleFormReset = (e) => {  reset(    { firstName: "Welly", lastName: "Shen" }, // Update the default values    ["isSubmitted", "submitCount"], // Don't reset the "isSubmitted" and "submitCount" state    e // Pass the event object to the "onReset" handler  );
  // We can also pass a callback as the "values" parameter, similar to React's setState callback style  reset((prevValues) => ({ ...prevValues, firstName: "Bella" }));};

๐Ÿ‘‰๐Ÿป See the Reset Form to learn more.