Hey there! So, let me tell you a little story. Once upon a time, I was trying to learn how to handle forms in React. And let me tell you, it was not a walk in the park. I found myself scratching my head and wondering why on earth it was so difficult to understand. But then, after many cups of coffee and some late nights, it finally clicked! And now, I want to share my knowledge with all of you lovely people out there who might be struggling just like I was. So buckle up and get ready for some form-handling fun (yes, that’s a thing)! 😂
Introduction to Forms
In HTML, forms are used to collect user’s input which is generally sent to a server to process. Form can be visualized as a container for all input elements such as : text-fields, radio buttons, checkboxes, etc. You can learn more about forms here For example,
<form>
<label for="f-name">First name:</label>
<input type="text" id="f-name" name="f-name">
<label for="l-name">Last name:</label>
<input type="text" id="l-name" name="l-name">
</form>
Need for handling forms?
In HTML, when we submit a form, you will notice that the page refreshes itself.
However, since React stores the form data in state. If we don’t handle forms in React, the default behavior of the form will take place (i.e. it will refresh itself and the current state will be lost). This means that when the form is submitted the data entered by the user in the form will be lost forever.
Handling Forms in React
Now, that we know why Handling Form is so important, let’s get started on how to handle them. In React, we can handle form using two ways :
- Controlled Components
- Uncontrolled Components
Let's see how they differ from each other and their working.
Controlled Components
An form whose data is being controlled in such a way that it’s data is stored in the React state using useState()
and is updated using setState()
which can only be triggered by the user.
To create your own controlled component, we need to use the value
prop and the onChange
prop of the form element.
For example ,
import { useState } from "react";
const Form=()=>{
// To store data in state
const [data,setData]=useState("") // If you provide a value to the component, it must remain a string throughout its lifetime.
//To handle Submit
const handleSubmit=(event)=>{
event.preventDefault() //Prevents the default behaviour
alert('You have entered the name: '+ data)
}
//To handle change of the input
const handleChange=(event)=>{
setData(event.target.value)
event.preventDefault() //Prevents the default behaviour
}
return(
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={data} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
)
}
export default Form;
Handling Multiple Inputs
To handle multiple inputs, you can use name
attribute of an input element to access it and let the handler function choose what to do with it.
Note : For checkboxes, use
event.target.checked
instead ofevent.target.value
Example:
import { useState } from "react";
const Form=()=>{
const [state,setState]=useState({isGoing: true,numberOfGuests: 2})
const handleInputChange=(event)=>{
event.preventDefault();
const target=event.target
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
setState((prevState)=>{
return {...prevState,[name]:value}
})
console.log(state)
}
return(
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={state.isGoing}
onChange={handleInputChange}
/>
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={state.numberOfGuests}
onChange={handleInputChange}
/>
</label>
</form>
)
}
export default Form;
Using controlled components in React can be time-consuming because you have to write an event handler for every change in data. This can be frustrating when converting old code to React or using it with non-React libraries. In these cases, you might want to try uncontrolled components, which are another way to implement forms.
Uncontrolled Components
Even if you manage to create a form which can handle multiple inputs, it still wouldn’t solve the performance issues as the component would re-render after each state update.
Therefore, you may use uncontrolled components which makes use of useRef()
to get form values from the DOM(Document Object Model).
Example :
import { createRef } from "react"
const Form=()=>{
const input=createRef()
const handleSubmit=(event)=>{
event.preventDefault()
alert('A name was submitted: ' + input.current.value);
}
return(
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" ref={input} />
</label>
<input type="submit" value="Submit" />
</form>
)
}
export default Form
As we can see an uncontrolled component gets the form values from the DOM, and is much more easier to implement as well as much less code than controlled input.
However, it is still advised to use controlled components instead of uncontrolled components.
Conclusion
You can head over to all the Sandbox which I've embedded and try to understand the code more efficiently. Also, I suggest reading some official docs by React.
Farewell, my brave hobbits