How to Access Form Control Elements in the onSubmit Event Handler in React?

Let's suppose we have the following React component containing a form:

const Foo = () => {
    return (
        <form onSubmit={handleSubmit}>
            <input type="email" name="email" defaultValue="[email protected]" />
            <input type="number" name="age" min="18" max="60" defaultValue="18" />

            <input type="submit" />
        </form>
    );
};

To access form control elements in the onSubmit handler, we can do any of the following:

  1. Get Form Control Elements By Their Names;
  2. Get Form Control Elements By Their Index;
  3. Using a Reference to the Form Control Elements.

Get Form Control Elements By Their Names

We can access the form controls by using the value in the element's name attribute, for example, in the following way:

const handleSubmit = (event) => {
    event.preventDefault();

    const emailInput = event.target.email; // accessing directly
    const ageInput = event.target.elements.age; // accessing via `form.elements`

    console.log(emailInput.value); // output: '[email protected]'
    console.log(ageInput.value); // output: '18'
};

From the example above we can see that:

  • event.target refers to the HTMLFormElement element;
  • Names of form control elements must match the value specified in their respective name attributes;
  • Form controls can be accessed by their name in the following ways:
    • Directly (e.g. event.target.email), or;
    • By using the HTMLFormElement.elements property (e.g. event.target.elements.email), or;
    • By using the HTMLFormElement.elements.namedItem() method (e.g. event.target.elements.namedItem('email')).

The HTMLFormElement.elements property returns an HTMLFormControlsCollection object, which allows us to access form controls in that form by using the element's name, which is similar to using the HTMLFormControlsCollection.namedItem() method. The difference between the two is the fact that the former would return undefined if the element doesn't exist, while the latter would return null.

Get Form Control Elements By Their Index

We can access a form control element by its (zero-based) index in the form, in the following way:

const handleSubmit = (event) => {
    event.preventDefault();

    const emailInput = event.target[0]; // accessing directly
    const ageInput = event.target.elements[1]; // accessing via `form.elements`

    console.log(emailInput.value); // output: '[email protected]'
    console.log(ageInput.value); // output: '18'
};

Please note that HTMLFormElement.elements only takes into account form control elements; i.e., <button>, <fieldset>, <input> (except <input type="image" />), <object>, <output>, <select>, and <textarea>. Therefore, the index number of form control elements would depend on which of these elements exist in the form, and their order.

From the example above we can see that:

  • event.target refers to the HTMLFormElement element;
  • Form control elements' indexes are based on their order in the form;
  • Form controls can be accessed by their index in the following ways:
    • Directly (e.g. event.target[0]), or;
    • By using the HTMLFormElement.elements property (e.g. event.target.elements[0]), or;
    • By using the HTMLFormElement.elements.item() method (e.g. event.target.elements.item(0)).

The HTMLFormElement.elements property returns an HTMLFormControlsCollection object, which allows us to access form controls in that form by its index, which is similar to using the HTMLFormControlsCollection.item() method. The difference between the two is the fact that the former would return undefined if the element doesn't exist, while the latter would return null.

Using a Reference to the Form Control Elements

Using the React.useRef() hook, we can reference an element easily. For example, to be able to reference "email" and "age" input fields in the onSubmit handler, we can do something like the following:

const Foo = () => {
    const emailInput = useRef(null);
    const ageInput = useRef(null);

    const handleSubmit = (event) => {
        event.preventDefault();

        console.log(emailInput?.current?.value); // output: '[email protected]'
        console.log(ageInput?.current?.value); // output: '18'
    };

    return (
        <form onSubmit={handleSubmit}>
            <input type="email" ref={emailInput} name="email" defaultValue="[email protected]" />
            <input type="number" ref={ageInput} name="age" min="18" max="60" defaultValue="18" />

            <input type="submit" />
        </form>
    );
};

The current property of the reference object holds the actual reference to the element.


This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.