Linguine Code

How to get form data on submit in ReactJS

Let’s say you have a form, and you have handleSubmit() function when a user clicks on the button.

How do you get the form data in that handleSubmit() function?!


const handleSubmit = () => {
  // ... get data form
  // ... submit to API or something
}

const FooBarForm = () => {
  return (
    <>
      <label>
        Username
        <input />
      </label>
      <br />
      <label>
        Password
        <input />
      </label>
      <br />
      <button onClick={handleSubmit}>Submit</button>
    </>
  );
}

Ideal solution: Use React setState or useState

You may use React class setState method or the React hook useState. In this example I will be using useState.

First, above my functional component I will create a new variable object called, initialFormData.


const initialFormData = Object.freeze({
  username: "",
  password: ""
});

Now I will update my functional component, FooBarForm.


const FooBarForm = () => {
  const [formData, updateFormData] = React.useState(initialFormData);

  const handleChange = (e) => {
    updateFormData({
      ...formData,

      // Trimming any whitespace
      [e.target.name]: e.target.value.trim()
    });
  };

  const handleSubmit = (e) => {
    e.preventDefault()
    console.log(formData);
    // ... submit to API or something
  };

  return (
    <>
      <label>
        Username
        <input name="username" onChange={handleChange} />
      </label>
      <br />
      <label>
        Password
        <input name="password" onChange={handleChange} />
      </label>
      <br />
      <button onClick={handleSubmit}>Submit</button>
    </>
  );
};

Let’s do a quick code breakdown.

The first chunk of code inside FooBarForm is to initialize React useState.


const [formData, updateFormData] = React.useState(initialFormData);

I’m providing initialFormData as my initial state value. If you’re not familiar with React useState, read up on it here.

The next snippet of code that’s important are my handler functions handleChange(), and handleSubmit().


const handleChange = (e) => {
  updateFormData({
    ...formData,

    // Trimming any whitespace
    [e.target.name]: e.target.value.trim()
  });
};

const handleSubmit = (e) => {
  e.preventDefault()
  console.log(formData);
  // ... submit to API or something
};

The first thing you should’ve notice is that I moved my handleSubmit() function inside FooBarForm functional component.

I did that so I can just access the formData variable right away.

You can extract these functions out of the functional component, but will require you to write your functions to allow values to pass through an event handler function. You can read up on that over here.

The handleChange() function is a critical piece. It’s responsible for updating my React state.

handleChange() is going to grab the element’s name value and map it to the formData state object.

Since it’s a string value, I’m trimming any white spaces.

The next update to this form is just updating the <input> elements.


<label>
  Username
  <input name="username" onChange={handleChange} />
</label>
<br />
<label>
  Password
  <input name="password" onChange={handleChange} />
</label>
<br />
<button onClick={handleSubmit}>Submit</button>

I’ve given each input field its own name property. The value of each name matches the initialFormData property.

So each input element is mapped to its own formData property.

I’m also attaching my handleChange() function to each input element onChange event.

That’s it!

When you fill out the form, and click the submit button the console will display


Object {username: "your string value", password: "your string value"}

Now, I want to show you another method that works, but is NOT the ideal solution.

Not ideal solution: useRef

You might be tempted to use React useRef because it’s easier to grab the element reference rather than doing all the useState boilerplate code.


const FooBarForm = () => {

  const usernameRef = React.useRef();
  const passwordRef = React.useRef();

  const handleSubmit = () => {
    console.log(usernameRef.current.value, passwordRef.current.value);
  };

  return (
    <>
      <label>
        Username
        <input ref={usernameRef} />
      </label>
      <br />
      <label>
        Password
        <input ref={passwordRef} />
      </label>
      <br />
      <button onClick={handleSubmit}>Submit</button>
    </>
  );
};

React useRef has its use-cases, but capturing form data is not one of them.

If you like to learn when to use React useRef, check out this article piece here.