React Forms
Where does the data go?
There are various approaches to handling forms, but mostly they boil down to one decision: where do you want to keep the form data?
- in component state (controlled components)
- in the DOM, using refs (uncontrolled components)
Generally it is preferred to handle form data with controlled components rather than using an uncontrolled form. Uncontrolled forms can make it harder to manage and validate form state, especially in more complex scenarios. It is therefore recommended to use controlled components as they provide more structured and manageable ways to handle data in forms.
Controlled components
Here's an example showing a form that is using controlled components:
const [formData, setFormData] = useState({name: '',description: '',})return (<form onSubmit={handleSubmit}><label htmlFor="name">Name</label><input type="text"name="name"value={formData.name}onChange={handleChange}/><label htmlFor="description">Description</label><textareaname="description"value={formData.description}onChange={handleChange}/><input type="submit" value="Add" /></form>)
Notice that this has a value
prop on each form element. This means that whatever is in the component state at that location will also be shown in the form.
Change handlers
Each input also has an onChange
prop which calls the handleChange
function each time the user types a key. Take a look at how we could define it:
const handleChange = (evt) => {const field = evt.target.namesetFormData({...formData,[field]: evt.target.value})}
If you haven't seen this sort of thing before, it's called computed property name syntax. Whatever string the variable field
contains will become the property name.
Submit handlers
The submit handler will be called when the user submits the form. As seen below, it first needs to prevent the default behaviour of the form (as we do not want it making requests to the server) before performing whatever action is required with the collected form data. Once done, we may also choose to reset the state to empty values (as below).
const handleSubmit = (evt) => {evt.preventDefault()// doSomething(formData)setFormData({name: '',description: ''})}
What about validation? Well, we could check each property and make sure it wasn't empty:
const { name, description } = formDataif (name.length && description.length) {doSomething(formData)}
Once it gets much more complex than that, you'll need to decide whether to continue writing your own form logic or relying on an existing library to do it for you.