Form Handling in React

Forms are essential for collecting user input and submitting data to the backend. In React, you can handle forms using controlled components to manage form state effectively.

Form in React

We have a form in HTML, using of form we input data from user and pass it in backend

Form data and state with single input data

We create from using a controlled component, here we can get user input data and pass it in the backend.

First we can start with only one input field.

<input type="text" placeholder="username" />

Here we see this is an uncontrolled form because here we cannot access user data. So we get user imputed data we work with onChange function.

const username = (event) => {
    console.log(event.target.value)
}
return ( <>
    <input type="text" placeholder="username" onChange={username} />
</> )

Here we access the user imputed value in the console but now we store it into state.

const [usernameState, setusernameState] = useState("")
const username = (event) => {
    setusernameState(event.target.value)
}
return ( <>
    <h2>@{usernameState}</h2>
    <input type="text" placeholder="username" onChange={username} />
</> )

Here we can access and store user imputed value in state but we cannot control non-imputed value or validation.

const username = (event) => {
    let val = event.target.value
    if(val === 'username' || val === "admin") {
        setusernameState("")
        alert(`You cannot enter username as ${val}.`)
    } else { setusernameState(val) }
}

But here we see, our state is now empty but the input field has a value so we can pass the state value to the input field.

<input type="text" placeholder="username" value={usernameState} onChange={username} />

Form data and state with multiple input data

We see above single data and state but in form we have never single data, so how can we handle multiple data in form.

Creating multiple states

const [usernameState, setusernameState] = useState("")
const [nameState, setnameState] = useState("")
const [passwordState, setpasswordState] = useState("")

const username = (event) => {
    setusernameState(event.target.value)
}
const name = (event) => {
    setnameState(event.target.value)
}
const password = (event) => {
    setpasswordState(event.target.value)
}
return ( <>
    <h1>Hii {nameState}</h1>
    <form>
        <h2>@{usernameState}</h2>
        <input type="text" placeholder="username" 
            value={usernameState} onChange={username} />
        <input type="text" placeholder="name" value={nameState} onChange={name} />
        <input type="password" placeholder="password" 
            value={passwordState} onChange={password} />
    </form>
</> )

Here we see we create multiple states but we also use substates. And store data in only one state.

const [state, setState] = useState({
    usernameState: "", nameState: "", passwordState: ""
})
const {usernameState, nameState, passwordState} = state
const username = (event) => {
    setState(prevState => { return {...prevState, usernameState: event.target.value} })
}
const name = (event) => {
    setState( prevState => { return {...prevState, nameState: event.target.value} })
}
const password = (event) => {
    setState( prevState => { return {...prevState, passwordState: event.target.value} })
}

Submit data of form for show data

We above see how we can change the data onChange but sometimes when data submit then show on fields. So we can now see how we can handle the submit function and button onsubmit event within the form.

We have created a new state and store presenting data on that state.

const [data, setData] = useState({
    usernameData: "",
    nameData: "",
})
const { usernameData, nameData } = data

We can also change the data display variable name from state to data.

<h1>Hii {nameData}</h1>
<form>
    <h2>@{usernameData}</h2> // below code is same
</form>

Now we cannot use the onSubmit event on button but we use this event on form so when we click on submit button data will be submitted.

<form onSubmit={dataSubmit}>
    // Inner code is same
</form>

Then we defined this event function.

const dataSubmit = (event) => {
    setData(prevData => { return { 
        ...prevData, usernameData: usernameState, nameData: nameState
    } }) }

But here we are facing one problem when we submit data page load and data cannot show. So we prevent this default submit method.

const dataSubmit = (event) => { 
    event.preventDefault()
    // below code is same
}

Form data with multiple input data and name

We can see above, we work with multiple data and input but here we can see how we can easily use the name attribute to store data in value.

Above we see how to handle multiple input field data with different function calling.

const username = (event) => {
    setState(prevState => { return {...prevState, usernameState: event.target.value} })
}
const name = (event) => {
    setState( prevState => { return {...prevState, nameState: event.target.value} })
}
const password = (event) => {
    setState( prevState => { return {...prevState, passwordState: event.target.value} })
}

Here we can see how to handle multiple input field data in single function calling.

First we add a name attribute in our input fields. The name value is the same as the subState value. And using different functions we use a single function in all input fields onChange events.

<input type="text" placeholder="username"
    name="usernameState"
    value={usernameState}
    onChange={states} />
<input type="text" placeholder="name"
    name="nameState"
    value={nameState}
    onChange={states} />
<input type="password" placeholder="password"
    name="passwordState"
    value={passwordState}
    onChange={states} />

Now, we create functions that use name value and store data in state.

We access name and value attributes and compare names with states and store data into state.

const states = (event) => {
    let value = event.target.value
    let name = event.target.name

    setState(prevState => {
        if (name === "usernameState"){
            return { ...prevState, usernameState: value }
        } else if (name === "nameState"){
            return { ...prevState, nameState: value }
        } else if (name === "passwordState"){
            return { ...prevState, passwordState: value }
        }
    })
}

Here also we compare all data manually but we simply use name and store value.

const states = (event) => {
    let {name, value} = event.target
    setState(prevState => { return { ...prevState, [name]: value } })
}

Form Data and State with a Single Input Field

We will start with a single input field to understand the basics of form handling.

Uncontrolled Form

An uncontrolled form does not manage the input data in the component state.

<input type="text" placeholder="username" />

Controlled Form

To manage the input data, we use the onChange event to update the state.

import React, { useState } from 'react';

const SingleInputForm = () => {
  const [username, setUsername] = useState('');

  const handleUsernameChange = (event) => {
    setUsername(event.target.value);
  };

  return (
    <>
      <input type="text" placeholder="username" onChange={handleUsernameChange} />
    </>
  );
};

export default SingleInputForm;

Here, we access and store the user input value in the state.

Adding Validation

We can add validation logic within the onChange handler to control the input.

const handleUsernameChange = (event) => {
  let val = event.target.value;
  if (val === 'username' || val === 'admin') {
    setUsername('');
    alert(`You cannot enter username as ${val}.`);
  } else {
    setUsername(val);
  }
};

return (
  <>
    <h2>@{username}</h2>
    <input type="text" placeholder="username" value={username} onChange={handleUsernameChange} />
  </>
);
Warning

Always validate user input to prevent invalid data from being processed.

Form Data and State with Multiple Input Fields

Handling multiple input fields involves managing multiple pieces of state.

Using Multiple States

import React, { useState } from 'react';

const MultiInputForm = () => {
  const [username, setUsername] = useState('');
  const [name, setName] = useState('');
  const [password, setPassword] = useState('');

  return (
    <>
      <h1>Hi {name}</h1>
      <form>
        <h2>@{username}</h2>
        <input type="text" placeholder="username" value={username} onChange={(e) => setUsername(e.target.value)} />
        <input type="text" placeholder="name" value={name} onChange={(e) => setName(e.target.value)} />
        <input type="password" placeholder="password" value={password} onChange={(e) => setPassword(e.target.value)} />
      </form>
    </>
  );
};

export default MultiInputForm;

Using a Single State Object

const [formData, setFormData] = useState({
  username: '', name: '', password: ''
});

const { username, name, password } = formData;

const handleChange = (event) => {
  setFormData(prevState => ({ ...prevState, [event.target.name]: event.target.value }));
};

return (
  <>
    <h1>Hi {name}</h1>
    <form>
      <h2>@{username}</h2>
      <input type="text" placeholder="username" name="username" value={username} onChange={handleChange} />
      <input type="text" placeholder="name" name="name" value={name} onChange={handleChange} />
      <input type="password" placeholder="password" name="password" value={password} onChange={handleChange} />
    </form>
  </>
);
Deep Dive

Using a single state object for multiple inputs simplifies state management and reduces boilerplate code.

Submitting Form Data

We can handle form submission to process the collected data.

Example of Form Submission

import React, { useState } from 'react';

const FormSubmission = () => {
  const [formData, setFormData] = useState({ username: '', name: '', password: '' });
  const [submittedData, setSubmittedData] = useState({ username: '', name: '' });

  const handleChange = (event) => {
    setFormData(prevState => ({ ...prevState, [event.target.name]: event.target.value }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    setSubmittedData({ username: formData.username, name: formData.name });
  };

  const { username, name, password } = formData;
  const { username: submittedUsername, name: submittedName } = submittedData;

  return (
    <>
      <h1>Hi {submittedName}</h1>
      <form onSubmit={handleSubmit}>
        <h2>@{submittedUsername}</h2>
        <input type="text" placeholder="username" name="username" value={username} onChange={handleChange} />
        <input type="text" placeholder="name" name="name" value={name} onChange={handleChange} />
        <input type="password" placeholder="password" name="password" value={password} onChange={handleChange} />
        <button type="submit">Submit</button>
      </form>
    </>
  );
};

export default FormSubmission;
Info

Prevent the default form submission behavior to avoid page reloads using event.preventDefault().

Task

Create and Manage a React Form

Objective: Create a React form with multiple input fields and manage their state effectively.

  1. Create a Controlled Form Component:

    • Create a new file UserForm.jsx.
    • Define a form with three input fields: username, name, and password.
  2. Manage Form State:

    • Use a single state object to manage all form inputs.
    • Implement onChange handlers for all inputs to update the state.
  3. Handle Form Submission:

    • Add a submit button to the form.
    • Implement the onSubmit handler to prevent default form submission and display the submitted data.
  4. Add Validation:

    • Add basic validation to ensure none of the input fields are empty.
    • Display appropriate error messages if validation fails.
import React, { useState } from 'react';

const UserForm = () => {
  const [formData, setFormData] = useState({ username: '', name: '', password: '' });
  const [submittedData, setSubmittedData] = useState(null);

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData(prevState => ({ ...prevState, [name]: value }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    if (formData.username && formData.name && formData.password) {
      setSubmittedData(formData);
    } else {
      alert('All fields are required.');
    }
  };

  return (
    <div>
      <h1>Submit Your Information</h1>
      <form onSubmit={handleSubmit}>
        <input type="text" name="username" placeholder="username" value={formData.username} onChange={handleChange} />
        <input type="text" name="name" placeholder="name" value={formData.name} onChange={handleChange} />
        <input type="password" name="password" placeholder="password" value={formData.password} onChange={handleChange} />
        <button type="submit">Submit</button>
      </form>
      {submittedData && (
        <div>
          <h2>Submitted Data</h2>
          <p>Username: {submittedData.username}</p>
          <p>Name: {submittedData.name}</p>
        </div>
      )}
    </div>
  );
};

export default UserForm;

By completing this task, you'll gain practical experience in implementing and managing form state in React, handling form submissions, and validating user inputs.