0

I am building a game that players can attack each other by turn. So first I set the name, jobmanually and generate life,damage,magic randomly in componentWillMount().

enter image description here

I hope that every time I submit the attack form, certain amount of life with be reduced from the attacked person. But now every time I submit, the whole state is regenerated(with all kinds of bugs).

enter image description here Can I do something to solve it?

app.js: https://ghostbin.com/paste/ype2y

attack.js: https://ghostbin.com/paste/wzm3m

Shukai Ni
  • 457
  • 2
  • 6
  • 17
  • Can't really tell if that's your error, but in your `app.js` you're changing your state directly `players.index2.life.set(life-damage);` The variables are passed by reference. You should make a copy of players to work on or just call `setState(...)` down on `life` – Björn Böing Jun 14 '17 at 12:58
  • @Bjoern it seems not the main one, I still found the error after fixing this. – Shukai Ni Jun 14 '17 at 13:15

2 Answers2

3

I noticed that you do a lot of:

let players = this.state.players

which you are not supposed to do. Array is an object in js so here you are passing by reference. This means that every modification to the var players actually has side effects and modifies the state which you should never do. I generally recommend to never use in-place operations like splice, and to always use a copy of the state. In this case you can do:

let players = this.state.players.slice()

and from then on any modification to the players var does NOT affect the state. Double check you are not doing this anywhere else in your code. On top of that you should use the constructor only to set up and initiate your state. Otherwise every time the componentWillMount method is called your state is regenerated which is probably not the behavior you are expecting.

EDIT

I figured I could give you more pointers for what you are trying to do with arrays, as a general rule of thumb I follow this approach. If my new state has an array field which is a subset of the previous one then I use the .filter method, if the array of my new state needs to update some of its entries then I use the .map method. To give you an example on player deletion, I would have done it this way:

handleDeletePlayer(id) {
  this.setState(prevState => ({
    players: prevState.players.filter(player => player.id !== id)
  }));
}
G4bri3l
  • 4,996
  • 4
  • 31
  • 53
  • Thank you for your help, it worked. Would you please also see another problem in this code? https://stackoverflow.com/questions/44592225/react-jswhy-react-cannot-find-the-object – Shukai Ni Jun 16 '17 at 14:59
1

Your initial state should be generated in the constructor. This is done only once and will not be repeated when components props are updated.

Deividas
  • 6,437
  • 2
  • 26
  • 27