React setState with useState

Viewed 71

I have this little visibility changer, and it works flawlessly for changing the attribute of the visibility variable, but my problem is, that it deletes every other variable from "productsState". It shouldn't be keeping the other variables?

const listing = () => {
const visibility= !productsState.visibility;
setProdState({visibility : visibility})
}
3 Answers

Functional Updates

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:

setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

Your code should be updated to use a functional state update and spread in the previous state:

const listing = () => {
  setProdState(prevState => ({
    ...prevState,
    visibility: !prevState.visibility,
  }))
}

The other answers here that do one of the following are not correctly updating from the previous state (though there may not be any apparent or adverse side-effects):

  1. const visibility= !productsState.visibility; is toggling from the state of the current render, not the previous state.
  2. Some variation of setProdState({...productsState, visibility : visibility}) as again productsState is the state from the render cycle the update is enqueued in, not the previous state.

You can use spread operators here

const listing = () => {
const visibility= !productsState.visibility;
setProdState({...productsState, visibility : visibility})
}

Read more about spread syntax

as productsState is an object you can spread it when you pass it to setProdState or you can use Object.assign which has the same effect

setProdState({...productsState, visibility: visibility});

or

setProductState(Object.assign({}, productsState, {visibility: visibility}));
Related