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 });