Why is my state's other values being changed to undefined?

Viewed 85

any idea on why my state is being changed to undefined ?

The whole situation is that I initiate my state as:

const [state, setState] = useState({
email: '',
password: '',
loading: false,
errors: {}

And then this is what updates the email and password fields:

const handleChange = (event) => {
console.log("Target:",event.target)
console.log("Name:",event.target.name, "Value:", event.target.value)
setState({
  [event.target.name]: event.target.value
});
console.log("State after: ",state.email, state.password)

But the thing is, once I write one character into one of the form's fields e.g. username, other state's fields become undefined, maybe you could explain what's the problem here ?

Attached is my console screenshot and code snip.

login form

login form

console screenshot

console screenshot

4 Answers

this is different from class components state which is keeping the values..

so instead of doing :

setState({
  [event.target.name]: event.target.value
});

do:

setState({ ...state,
  [event.target.name]: event.target.value
});

you missed to spread other fileds values, that's why they've been removed once calling setState ,

use spread operator to preserve previous other values as :

setState({
   ...state,
  [event.target.name]: event.target.value
});

You should consider using prevState when setting object defined with useState:

setState(prevState => ({ ...prevState,
  [event.target.name]: event.target.value
}));

Problem is that unlike this.setState(...) in class components, state updater function in functional components doesn't merges the old state with the new state automatically. So its your job to merge the new state with the old state.

From React Docs:

Note

Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax

Currently, the way you are updating the state, it completely overwrites the existing state. To prevent this, you can use the spread syntax to merge the existing state with the new state.

setState({
  ...state,
  [event.target.name]: event.target.value
});
Related