Rilaykit Logorilaykit ✨
Forms

The useForm Hook

Learn how to access and control the form state from your custom components using the useFormContext hook.

The useFormContext hook is the primary way to interact with a form's state when building custom components. It provides access to all the form's data, errors, and actions, allowing you to create rich, interactive form experiences.

How to use it

Import the hook from @rilaykit/forms and call it inside any component that is a child of a FormProvider.

import { useFormContext } from '@rilaykit/forms';

function MyCustomField() {
  const form = useFormContext();

  // You can now access form state and methods
  // e.g., form.formState.values, form.setValue(), etc.
  
  return (
    <div>
      <p>Is form dirty? {form.formState.isDirty ? 'Yes' : 'No'}</p>
      <button onClick={() => form.setValue('firstName', 'Rilay')}>
        Set First Name
      </button>
    </div>
  );
}

The useFormContext hook will only work for components rendered inside a FormProvider.

Returned Values

The useFormContext hook returns an object containing the form's state and functions to manipulate it.

State Properties

These properties provide a real-time snapshot of the form's state.

  • formState: An object containing the core state of the form.
    • values: The current values of all form fields.
    • errors: An object holding validation errors for each field.
    • validationState: An object with the validation state for each field ('idle', 'validating', 'valid', or 'invalid').
    • touched: An object indicating which fields the user has interacted with.
    • isDirty: true if the user has modified any field from its initial value.
    • isValid: true if there are no validation errors.
    • isSubmitting: true when the form submission process is active.
  • formConfig: The full configuration object that was used to create the form.

Action Functions

These functions allow you to interact with and control the form.

  • setValue(fieldId, value): Updates the value of a specific field.
  • setFieldTouched(fieldId, touched?): Marks a field as "touched".
  • setError(fieldId, errors): Manually sets validation errors for a field. This will also set the form's overall isValid state to false.
  • clearError(fieldId): Clears errors for a specific field. Note: this does not automatically set the form's isValid state to true; a full form validation might be needed.
  • validateField(fieldId, value?): Triggers validation for a single field. The optional value argument allows immediate validation without waiting for a re-render.
  • validateForm(): Validates all fields in the form.
  • reset(values?): Resets the form to its initial state or to a new set of values.
  • submit(): Programmatically triggers the form submission process.

Example: Custom Submit Button

You can use useFormContext to create custom components that react to the form's state. Here is an example of a submit button that shows a loading state and is disabled if the form is invalid.

import { useFormContext } from '@rilaykit/forms';

export function CustomSubmitButton() {
  const { formState, submit } = useFormContext();
  const { isSubmitting, isValid, isDirty } = formState;

  const handleClick = (event: React.MouseEvent) => {
    event.preventDefault(); // Prevent default form submission
    submit();
  };

  return (
    <button 
      type="submit"
      onClick={handleClick}
      // Disable if submitting, or if the form is not dirty and invalid
      disabled={isSubmitting || !isDirty || !isValid}
    >
      {isSubmitting ? 'Submitting...' : 'Submit Form'}
    </button>
  );
}

This component connects to the form's state to provide clear feedback to the user, improving the overall user experience.