0

I am trying to build a battleShip game using React.

I have a state like this inside my component, every coordinate has a list with two 'states', 'empty' if there is not a ship ('busy' if there is) in it and 'intact' the coordinate hasn't been hit ('hit' if it has).

this.state = {
  status: {
    A1: ['empty', 'intact'],
    B1: ['busy', 'intact']
  }
}

What I want to do is: When I click in a coord in the battleShip grid to shoot it, I want to set only the second element in the list to 'hit' and leave the first element without changes.

Something like this:

handleClick = (e) => {
  const coord = e.target.id; //get the coord from the element clicked, like 'A1'
  this.setState({ status: { coord[1]: 'hit' } });       
}

So I want my new State to be :

this.state = {
  status: {
    A1: ['empty', 'hit'],
    B1: ['busy', 'intact']
  }
}

How do I write this.setState({ status: { coord[1]: 'hit' } }) in the correct way, so that my new State is exactly like above?

Tholle
  • 108,070
  • 19
  • 198
  • 189
Plínio Helpa
  • 137
  • 1
  • 9
  • Possible duplicate of [Correct modification of state arrays in ReactJS](https://stackoverflow.com/questions/26253351/correct-modification-of-state-arrays-in-reactjs) – jmargolisvt Jul 05 '18 at 21:03

2 Answers2

1
let newStatus = {...this.state.status};
newStatus.A1[1] = 'hit';
this.setState({status: newStatus});
  • This will mutate the `A1` array. `newStatus.A1 = [newStatus.A1[0], 'hit'];` should work. – Tholle Jul 05 '18 at 21:14
  • Is it a problem to mutate the copied object's array? – dotnetdev4president Jul 05 '18 at 21:16
  • Yes, in this case with arrays. Had `this.state.status` only contained keys with string values, it would have been fine. Try `const a = [1]; const s1 = { a }; const s2 = {...s1}; s1.a === s2.a` and you will see it's still the same array. – Tholle Jul 05 '18 at 21:21
1

You could use property accessors and slice for this.

For example:

handleClick = (e) => {
    const coord = e.target.id; //get the coord from the element clicked, like 'A1'
    const current = this.state.status[coord];
    let newVal = current.slice(); // Clone array
    newVal[1] = 'hit';
    this.setState({ status: { ...this.state.status, [coord]: newVal } });
};

That is assuming e.target.value is a string.

Here is the documentation on property accessors from MDN.

NoxelNyx
  • 995
  • 1
  • 7
  • 21