Reputation: 15
Little context, I am trying to create a form for for getting User Signup.
I first wrote code as following .
import { useState } from 'react';
const SignupComponent = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
error: '',
loading: false,
message: '',
showForm: true
})
const { name, email, password, error, loading, showForm } = formData;
const onChange = e => {
setFormData({ ...formData, error: false, [e.target.name]: e.target.value })
console.log(name)
}
const handleSubmit = async e => {
e.preventDefault();
console.table({ name, email, password, error, loading, showForm })
}
const signupForm = () => {
return (
<form onSubmit={handleSubmit}>
<div className="form-group">
<input type="text" className="form-control" placeholder="Enter Your Name" values={name} onChange={e => onChange(e)} />
</div>
<div className="form-group">
<input values={email} onChange={e => onChange(e)} type="email" className="form-control" placeholder="Enter Your Email" />
</div>
<div className="form-group">
<input values={password} onChange={e => onChange(e)} type="password" className="form-control" placeholder="Enter Your Password" />
</div>
<div>
<button className="btn btn-primary">Signup</button>
</div>
</form>
);
};
return <React.Fragment>{signupForm()}</React.Fragment>};
export default SignupComponent;
I noticed that in this code snippet, the state in setFormData is not getting updated, console logging name or any other value returns a empty string.
But after tweaking the code as such
import { useState } from 'react';
const SignupComponent = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
error: '',
loading: false,
message: '',
showForm: true
})
const { name, email, password, error, loading, showForm } = formData;
const handleChange = value => (e) => {
setFormData({ ...formData, error: false, [value]: e.target.value })
console.log(name)
}
const handleSubmit = async e => {
e.preventDefault();
console.table({ name, email, password, error, loading, showForm })
}
const signupForm = () => {
return (
<form onSubmit={handleSubmit}>
<div className="form-group">
<input type="text" className="form-control" placeholder="Enter Your Name" values={name} onChange={handleChange('name')} />
</div>
<div className="form-group">
<input values={email} onChange={handleChange('email')} type="email" className="form-control" placeholder="Enter Your Email" />
</div>
<div className="form-group">
<input values={password} onChange={handleChange('password')} type="password" className="form-control" placeholder="Enter Your Password" />
</div>
<div>
<button className="btn btn-primary">Signup</button>
</div>
</form>
);
};
return <React.Fragment>{signupForm()}</React.Fragment> };
export default SignupComponent;
Makes the code work and result is as desired. As in this image. 2nd way
Why is this behaving like this. Why is the first way not working.
Upvotes: 0
Views: 513
Reputation: 157
see docs, https://reactjs.org/docs/thinking-in-react.html
React’s one-way data flow (also called one-way binding) keeps everything modular and fast.
Important thing to solve your question.
signupForm
render function is declared in FC.First. change signupForm
render function to FC component.
Second, Pass props to component. Thrid, re-used them.
import React from 'react'; // React is required to render JSX
const FormInput = ({
type,
placeholder,
value,
onChange,
}) => (
<div className="form-group">
<input type={type} className="form-control" placeholder={placeholder} value={value} onChange={onChange} />
</div>
);
const SignupComponent = () => {
const [formData, setFormData] = React.useState({
name: '',
email: '',
password: '',
error: false,
loading: false,
message: '',
showForm: true,
});
const {
name, email, password, error, loading, showForm,
} = formData;
const handleChange = (value) => (e) => {
setFormData({
...formData,
error: false,
[value]: e.target.value,
});
console.log(name);
};
const handleSubmit = async (e) => {
e.preventDefault();
console.table({
name, email, password, error, loading, showForm,
});
};
return (
<form onSubmit={handleSubmit}>
<FormInput type="text" value={name} placeholder="Enter Your Name" onChange={handleChange('name')} />
<div>
<button type="submit" className="btn btn-primary">Signup</button>
</div>
</form>
);
};
export default SignupComponent;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Upvotes: 0
Reputation: 326
You forgot the name attribute in your inputs, and the value attribute without s
<input name="email" value={email} onChange={onChange} ... />
then
const onChange = e => {
// The event will get passed as an argument even if you don't bind it in onChange={onChange}.
console.log(e.target.name, e.target.value)
setFormData({ ...formData, error: false, [e.target.name]: e.target.value })
}
The event will get passed as an argument.
It works for the second cause you're passing the name as an argument
Upvotes: 2