I am attempting to send form data from my react client to my nodejs server; however, upon submitting the form, only the last property of the state is sent to my server. I know this is a client side issue, since with Postman, my entire form data is sent to my database.
It seems when I add a value to each property in my state, only that property is maintained in user. I haven’t been able to resolve this in the time I allotted myself, so I would appreciate another perspective / feedback on the issue.
const ModalForm = ({ show }) => {
if (!show) {
return null;
}
let [user, setUser] = useState({
firstName: '',
lastName: '',
email: '',
password: '',
age: ''
});
let handleChange = (e) => {
console.log('event name', e.target.name, 'event value', e.target.value);
setUser({
[e.target.name]: e.target.value
});
};
/*
currently, only the last prop and value are sending to my API
need to resolve so that all form data is sent to API
*/
let handleSubmit = (e) => {
e.preventDefault()
let data = user;
setUser({[e.target.name]: e.target.value});
axios.post('/new/user', data)
.then(res => console.log(res))
.catch(err => console.error(err))
}
console.log('user:', user);
return (
<div className='form-container'>
<form className='form-space' onSubmit={handleSubmit}>
<label>
First Name:<br/>
<input type='text' name='firstName' onChange={handleChange}/>
</label><br/>
<label>
Last Name:<br/>
<input type='text' name='lastName' onChange={handleChange}/>
</label><br/>
<label>
Email:<br/>
<input type='email' name='email' onChange={handleChange}/>
</label><br/>
<label>
Password:<br/>
<input type='password' name='password' onChange={handleChange}/>
</label><br/>
<label>
Age:<br/>
<input type='text' name='age' onChange={handleChange}/>
</label><br/>
<input type='submit' value='Submit' />
</form>
</div>
)
};
export default ModalForm;
Advertisement
Answer
useState state setters are not like setState in functional components; in functional components, properties of the state object are kept even when setState is called with an object lacking those properties. It’s like Object.assign.
In class components, starting with a state of { foo: true } and doing setState({ bar: true }) results in { foo: true, bar: true }.
But useState in functional components is not like that. Instead of merging the old state with the new state, the new state completely replaces the old state. Starting with a state of { foo: true } and doing setState({ bar: true }) results in { bar: true }.
Here, since you’re doing
setUser({
[e.target.name]: e.target.value
});
any previous properties of user get lost.
Spread the previous value of user into the new state instead, so the previous state properties get preserved:
setUser({
...user,
[e.target.name]: e.target.value
});