Diagathe Josué
Diagathe Josué

Reputation: 11966

I fail to setState my ReactJS state dynamically with a function

I'm trying to set the display of my ReactJS component dynamically.

Basically the game is the following : the user push a button, then the value of the affiliate state is set to true. Allowing to handle the displaying of the buttons.

However my state doesn't changes when I push a button, despite I log it after the change would have occurred. However I have set my state. I wonder what going wrong.

Here my tiny snippet, easy testable and reproducible :

https://codesandbox.io/s/21963yy01y

Here my snippet.js :

export default class App extends React.Component {

  state = {
    displaySelection: false,
    displayCreate: false,
    displayUpdate: false,
    displayDelete: false,
  }

  viewSelection = (e) => {
    e.preventDefault();

    Object.keys(this.state).map((key, index) => {

      // console.log("key value: ", key)
      console.log("target name: ", e.target.name)
      if (key === e.target.name) {
        console.log(e.target.name, " set to true =)")
        return this.setState({ [e.target.name]: true }, console.log("display state: ", this.state))

      } else {
        this.setState({ [e.target.name]: false })
      }
    });



  } 

  render() {
    return (
      <div className="App">
        <button onClick={this.viewSelection}> Launch the Object.keys function =) splay</button>

        <div >
          <button name="displayCreate" onClick={this.viewSelection}> Create </button>
          <button name="displayUpdate" onClick={this.viewSelection}> Update </button>
          <button name="displayDelete" onClick={this.viewSelection}> Delete </button>
          <button name="displaySelection" onClick={this.viewSelection}> O </button>
        </div>
      </div>
    );
  }
}

Why when I push a button the state of this button doesn't change ?

Any hint would be great, thanks

Upvotes: 3

Views: 48

Answers (1)

bwalshy
bwalshy

Reputation: 1135

Found a flaw in your logic. In your else statement in your viewSelection function, you have:

else {
  this.setState({ [e.target.name]: false });
}

So in every iteration of the loop, you are setting the target that was clicked to false in state. You can solve that by changing e.target.name to key, like so:

else {
  this.setState({ [key]: false });
}

So that way you're only changing the key that isn't the current target. But this is still inefficient because you're still running setState 4 times (1 for each key in state). One more efficient way to achieve what you're looking for is to have an object (essentially a copy of what's in state) with the keys set to false by default. Then take the target from the click and set that to true, like so:

viewSelection = e => {
  e.preventDefault();

  let newValues = {
    displaySelection: false,
    displayCreate: false,
    displayUpdate: false,
    displayDelete: false
  };

  newValues[e.target.name] = true;

  this.setState(newValues);
}

Upvotes: 2

Related Questions