3

My code below is overwriting my array instead of adding on top of the array. I couldn't figure out why it is doing so.

state = { someArray: [] };

onButtonClick = () => {
  this.setState((state, props) => ({
    someArray: [...state.someArray, props.element]
  }));
};
X_C95
  • 89
  • 1
  • 6
  • Does this answer your question? [ECMAScript 6 arrow function that returns an object](https://stackoverflow.com/questions/28770415/ecmascript-6-arrow-function-that-returns-an-object) – CertainPerformance Sep 04 '20 at 02:45
  • 1
    Shouldn't it be `someArray: [...this.state.someArray, props.element]` – anjanesh Sep 04 '20 at 02:47
  • Sorry, I got a typo there, so I do have a pair of parenthesis outside the curly braces. There is no compile error. The array still gets overwritten. I passed the state as an argument of the callback function, so inside there I wrote `...state.sessions` – X_C95 Sep 04 '20 at 02:52

3 Answers3

1

It's because you're not spreading the existing state value for someArray. Try this:

onButtonClick = () => {
  this.setState((state, props) => ({
    someArray: [...state.someArray, props.element]
  }));
}
vich
  • 11,836
  • 13
  • 49
  • 66
  • Oh oops sorry, I have another typo there, I did have `...state.someArray` but the array is not updating, but overwriting – X_C95 Sep 04 '20 at 03:07
  • The code above should work. Make sure you have it exactly like that. If it still doesn't, you might have some other function updating state. You can also throw in a debugger statement or `console.log` inside of `setState` (you'd have to change the `=> ({` to just a `=> {` and do an explicit return). Are you using any of the component lifecycle methods? – vich Sep 04 '20 at 03:11
  • Im not using any lifecycle method. The only place that is changing the state `someArray` is inside this function – X_C95 Sep 04 '20 at 03:14
  • Did you copy-paste my code as-is? As the other answer points out, you need to wrap your curly braces in parentheses in order for the `setState` function to update your state. – vich Sep 04 '20 at 03:17
  • Yes, I have copied your code and tried running it, and console.log out, the array is still being overwriten. – X_C95 Sep 04 '20 at 03:21
  • Sounds like your issue is in another part of your code. Add some `console.log` statements in your component (e.g. inside render) and inspect your state value. – vich Sep 04 '20 at 03:33
0

The only thing was missing from your code is () to return the new state.

...
this.setState((s, p) => ({ ...etc })
...                     ^          ^

Otherwise it does work for me, see below:

class App extends React.Component {
  state = { someArray: [] };

  onButtonClick = () => {
    this.setState((state, props) => ({
      someArray: [...state.someArray, props.element]
    }));
  }
  
  render(){
    return (
      <div>
        <button onClick={this.onButtonClick}>Add</button>
        {this.state.someArray}
      </div>
    )
  }
}

ReactDOM.render(<App element=">"/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
gazdagergo
  • 6,187
  • 1
  • 31
  • 45
0

After 3 days I finally figured out the way of solving this problem. So the answers from @gazdagergo and @vich are completely right. It is just that I have a parent component as a container holding all the items that need to be added into the array, and all the items are rendered out inside a child component. I originally declared the array inside the child component, which then generate a new array each time I add an item into the array causing the array to be 'overwritten'.

To solve, instead of declaring the array inside the child component, I moved the array declaration into the parent component, which eventually solved the problem.

X_C95
  • 89
  • 1
  • 6