Hello everyone, recently I came across a new way to handle React forms, maybe its something you know, maybe you've been doing this for years and think I am an Idiot for not knowing this earlier, but it is what it is so let's go.
Using react forms the old way
Let's consider a simple signup form that contains only 3 fields namely username, email, and password. Here's how I used to use forms earlier.
import React,{useState} from 'react';
const SignUp = () => {
const [username,setUsername] = useState("");
const [password,setPassword] = useState("");
const [email,setEmail] = useState("");
const handleEmailChange(e){
setEmail(e.target.value);
}
const handlePasswordChange(e){
setPassword(e.target.value);
}
const handleUsernameChange(e){
setUsername(e.target.value);
}
return(
<form>
<input type="text" placeholder="username" onChange={handleUsernameChange} value={username}/>
<input type="email" placeholder="email" onChange={handleEmailChange} value={email}/>
<input type="password" placeholder="password" onChange={handlePasswordChange} value={password}/>
<input type="submit" value="Submit"/>
</form>
);
}
Maybe you think wtf is this guy and why is the code is so bad. There's only one thing I can say to you, sorry. To the other people who think there's nothing wrong with the code, prepare to get your mind blown.
Let's look at the problems with the code first-
- Its a lot of state variables for handling a form, especially if you think about bigger forms with 10s of fields.
- The handleChange functions are totally redundant and can be easily refactored.
So, now let's look at the amazing code to handle forms -
import React,{useState} from 'react';
const SignUp = () => {
const [formData, setFormData] = useState({
username: "",
email: "",
password: "",
});
const handleChange=(e)=>{
const newFormData = {
...formData,
[e.target.name]:e.target.value
};
setFormData(newFormData);
}
return(
<form>
<input type="text" name="username" placeholder="username" onChange={handleChange} value={username}/>
<input type="email" name="email" placeholder="email" onChange={handleChange} value={email}/>
<input type="password" name="password" placeholder="password" onChange={handleChange} value={password}/>
<input type="submit" value="Submit"/>
</form>
);
}
Beautiful code, Right? Well, when I found it I thought it was amazing and worth sharing.
But before you leave, make sure that the formData
's keys are same as the input's name
, else you're code won't work properly.
That's pretty much it.
Thank you for reading. Bye
Top comments (13)
Is better to use prevState argument when chaning state based of previous state because
setState
is asynchronous and may cause unstable updates.or in more short form:
Thank you for the suggestion.
In the second example you forgot to rename your handlers to
handleChange
. This could be confusing for newbies.Anyway it's a good start, but as some others told you, you should rely on form libraries. I tested a lot of them and I kind of like final-form for building big forms and reusable fields, then I would recommend you Yup for the validation. The latter is working pretty well with any form library by the way.
Formik + Yup is very good combo.
Yes I used Formik before but got issues with null values and complex forms. I didn't encountered any of those issues with final-form which I'm using in production for a year now
Thanks for pointing it out, I've updated it.
I totally agree that third party libraries are excellent way of handling React forms.
I just found about this way and thought it was pretty neat.
Nice – a couple things I had to tweak to get working, though:
<input />
elements need names likename="username"
, otherwise the change handler doesn't know which state value to updateconst handleChange(e){}
needs to either beconst handleChange = (e) => {}
orfunction handleChange(e){}
Thanks for pointing it out
I agree this is a good writeup!!
I'd also suggest adding a validation layer.
I know you want to keep this as a simple example but that is also something basic to always add when working on forms.
Between required fields to ensuring the dat isn't being submitted with empty strings.
Many things could be added in the validation layer
This is a solved problem already. React Hook Form, Formik, React Final Form, etc... are solid libraries.
This trick is very nice! Thanks for sharing.
You're welcome. Thanks for reading
Fun fact: *This is recommended of reactjs.org
Read more here: reactjs.org/docs/forms.html#handli...