Noble Polygon
Noble Polygon

Reputation: 806

React destructuring state assignment

I have a program where I have a menu that can toggle the view of any item on screen. I was originally using useState to toggle each individual component

example:

const [buttonA, setButtonA] = useState(false)
const [buttonB, setButtonB] = useState(false)
//...etc

This functioned correctly when implemented. However, now I've been tasked with using a single object to handle all keys from Props in a class component:

example:

      layers:
        {
          propA: props.propA,
          propB: props.PropB,
//..etc
}

I have also implemented a function to show or hide an element on screen. It takes the JSON key and updates the layer view based on the toggle.

  showHideHandler = (key, value) => {
    const newLayers = { ...layers };
    newLayers[key] = value;
    this.setState({ layers: newLayers });
  };

I use this function in a modal to control the show/hide feature like this:

  <Button
     className={style.selector}
     onClick={() => showHideHandler('propA', !layers.propA)}
     > I AM PROP A
</Button>

Finally I am passing the prop values into a component like this for example:

{layers.propA ? (
<p> Visible </p>
):(
<p> Invisible</p>
)}

This toggle function works that I am able to show and hide element. However, the following problem is occurring.

When I first click on any button. The first thing that happens is that all the elements are hidden on the screen as if all the states are being set to hide. If I click the button a second time, the original component I want to hide shows the correct show hide action but all other items are still hidden.

I went back to check my toggle function const newLayers = { ...layers }; and made the following update to the newLayers const: const newLayers = this.setState.layers

  showHideHandler = (key, value) => {
    const newLayers = this.setState.layers;
    newLayers[key] = value;
    this.setState({ layers: newLayers });
  };

This now returns the error must use restructuring state assignment which shows the following error in the browser: Use callback in setState when referencing the previous state

I'm a bit stuck at this point and any help in the right direction would be greatly appreciated.

Upvotes: 0

Views: 1430

Answers (2)

Drew Reese
Drew Reese

Reputation: 203587

It looks like a warning is informing you to use a functional state update.

showHideHandler = (key, value) => {
  this.setState(prevState => {
    // spread previous layers state into new object
    const newLayers = { ...prevState.layers };
    newLayers[key] = value;
    return { layers: newLayers };
  });
};

Or more succinctly

showHideHandler = (key, value) => {
  this.setState(prevState => {
    return {
      layers: {
        ...prevState.layers,
        [key]: value,
      },
    };
  });
};

Upvotes: 1

aquinq
aquinq

Reputation: 1448

As @Red Baron said, const newLayers = this.setState.layers; is non-sense. You should mutate setState's first argument (representing the previous state) to update your state :

const showHideHandler = (key, value) => {
  this.setState((prevState) => ({
    layers: {
      ...prevState.layers,
      [key]: value,
    }
  }));
};

Upvotes: 1

Related Questions