0

I'm trying to update a nested object in React using setState, which is in a function that is called from a form onChange event. The code below works the first time it is called, but after that I get an error Cannot set properties of undefined (setting 'value'). What am I doing wrong?

const initialState = {
    email: { value: "", hasError: true, error: "" },
    password: { value: "", hasError: true, error: "" }
}

const [state, setState] = useState(initialState);

function handleChange(event) {
    setState(state[event.target.name].value = event.target.value);
}
PixelPaul
  • 2,609
  • 4
  • 39
  • 70
  • 1
    State is immutable, you need to copy the object first. See this question: [How to update nested state properties in React](https://stackoverflow.com/questions/43040721/how-to-update-nested-state-properties-in-react) – Enfield Li Aug 30 '22 at 23:23

1 Answers1

1

You cannot call setState like that. You need to get the previous value from setState. There is a prev argument in setState that allows you to pass the previous values into the function. You can use the spread operator (https://www.w3schools.com/REACT/react_es6_spread.asp) to keep all untouched values the same. For instance:

const initialState = {
  email: { value: "", hasError: true, error: "" },
  password: { value: "", hasError: true, error: "" }
}

const [state, setState] = useState(initialState);

function handleChange(event) {
  setState(prev => ({
    ...prev,
    email: {
      value: "value",
      hasError: false,
      error: ""
    }
  }));
}

Also - You can just check if there's an error by evaluating the error property. Something like !!state?.email?.error so you don't need the extra boolean in there (obviously if there's an error string, then it means there's an error). Just clear the error string on reset and it'll be false again.

Info on setState: https://reactjs.org/docs/faq-state.html#what-does-setstate-do

Joel Hager
  • 2,990
  • 3
  • 15
  • 44