Basic Form Handling With ReactJS
5 min read
Most software applications require a developer to know how to manage forms. But this task is one of the most struggling for many developers. However, managing forms is inevitable when you're a software developer. In my field which is web development, ReactJS is the most popular UI library at the time of this writing. But as devs migrate their projects to or started learning React, managing forms is still somehow hard. Let's take a look on how to work with forms with ReactJs using hooks
that it provides:
import React from 'react';
function App() {
// let's create a simple form first
return (
<form>
<input placeholder='First Name' />
<input placeholder='Last Name' />
<button type='submit'>Submit</button>
</form>
);
}
Now, our app should submit the form data to some remote server. But first, we need a way to extract the <input />
values. We can track the value of each <input />
using React's useState
hook:
import React from 'react';
function App() {
// adding the useState hook
const [firstName, setFirstName] = React.useState('');
const [lastName, setLastName] = React.useState('');
// let us sync the state of each <input /> with our states
// by providing a `value` and an `onChange` handler to our inputs
return (
<form>
<input
placeholder='First Name'
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<input
placeholder='Last Name'
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
<button type='submit'>Submit</button>
</form>
);
}
The next step is to gather all the input values and submit them as an object to the server. For this we are adding a submit handler for the form.
import React from 'react';
import { createUser } from '../some-fake-user-api-service';
function App() {
// adding the useState hook
const [firstName, setFirstName] = React.useState('');
const [lastName, setLastName] = React.useState('');
const handleSubmit = (e) => {
e.preventDefault(); // what `default` are we preventing anyway? 🧐
const userData = { firstName, lastName };
createUser(userData);
};
return (
<form onSubmit={handleSubmit}>
<input
placeholder='First Name'
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<input
placeholder='Last Name'
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
<button type='submit'>Submit</button>
</form>
);
}
Our form is done! We have managed to submit the form values to the server with ease. But for sure you're asking: How about validations? how about if the form grows complex? what about tracking if the form has been submitted or is submitting? Yeah, I know. Managing forms also means providing our users a better experience.
We'll address these questions in another post. For now, let's refactor our form a bit.
As you can see, each input of our form has a dedicated state and state setter. This approach is not good for bigger forms. Let's improve our current implementation by just using a single object called fields
.
import React from 'react';
import { createUser } from '../some-fake-user-api-service';
function App() {
// A better way
const [fields, setFields] = React.useState({
firstName: '',
lastName: '',
});
const handleSubmit = (e) => {
e.preventDefault();
createUser(fields);
};
// render markup here...
}
In order to know which input the user is editing and to properly assign values to our fields
state, we need to change our onChange
handler.
import React from 'react';
import { createUser } from '../some-fake-user-api-service';
function App() {
// A better way
const [fields, setFields] = React.useState({
firstName: '',
lastName: '',
});
// extract properties from fields
const { firstName, lastName } = fields;
const handleChange = (e) => {
// name -> the `name` attribute of the input
// value -> the actual value of the input
const { name, value } = e.target;
setFields((oldValues) => ({ ...oldValues, [name]: value }));
};
const handleSubmit = (e) => {
e.preventDefault();
createUser(fields);
};
return (
<form onSubmit={handleSubmit}>
<input placeholder='First Name' value={firstName} name='firstName' onChange={handleChange} />
<input placeholder='Last Name' value={lastName} name='lastName' onChange={handleChange} />
<button type='submit'>Submit</button>
</form>
);
}
With this approach, when we add other inputs, say an email
and a password
field, we don't have to change anything in our handleChange
function. What we just need to update is our fields
state.
import React from 'react';
import { createUser } from '../some-fake-user-api-service';
function App() {
// A better way
const [fields, setFields] = React.useState({
firstName: '',
lastName: '',
email: '',
password: '',
});
// extract properties from fields
const { firstName, lastName, email, password } = fields;
/** handlers here */
return (
<form onSubmit={handleSubmit}>
<input placeholder='First Name' value={firstName} name='firstName' onChange={handleChange} />
<input placeholder='Last Name' value={lastName} name='lastName' onChange={handleChange} />
<input placeholder='Email' type='email' value={email} name='email' onChange={handleChange} />
<input
placeholder='Password'
type='password'
value={password}
name='password'
onChange={handleChange}
/>
<button type='submit'>Submit</button>
</form>
);
}
This is how simple it is to handle basic forms with ReactJS. For future posts, I'll try to walk you through creating better forms using a library called react-hook-form
.
Happy coding!
-jep