0

I have two handler functions for an onClick event on a button. Basically they do the same thing but one is incrementing an element (passed as a parameter) in the state array while the other is decrementing (but not the same variable). Say I have an array of two elements. I want the first element to be incremented and the second element to be decremented (array[0]++ array[1]--).

HandleIncrement = instrumentUp => {
  // create a shallow copy of the array
  const tempCount = [...this.state.instrumentCount];
  // increment the desired instrument
  tempCount[instrumentUp] += 1;
  // update the state
  this.setState({
    instrumentCount: tempCount
  });
};

HandleDecrement = instrumentDown => {
  // create a shallow copy of the array
  const tempCount = [...this.state.instrumentCount];
  // decrement the desired instrument
  tempCount[instrumentDown] -= 1;
  // update the state
  this.setState({
    instrumentCount: tempCount
  });
};

I also have a button where these two methods are executed.

 onClick = {() => {
     this.HandleIncrement(0);
     this.HandleDecrmenet(1);
   }
 }

The output is not desired. If this was the array = [0 1], I wish the output to be [1 0] however the the output is [0 0]. I think this is because of these two functions being executed at the same time and so when they setState, HandleDecrement didn't use the updated state.

Should I be using something like async or await?

Clarity
  • 10,730
  • 2
  • 25
  • 35
  • 1
    You cannot `await` state changes because they get processed internally. The recommended solution to your problem is to write an additional function that handles both changes (but calls `setState` only once). Clarity's suggestion, if coded properly, will work though: https://codesandbox.io/s/magical-dubinsky-tkw6o –  Mar 09 '20 at 10:04
  • This has worked thank you! – Michael Michael Michael Mar 09 '20 at 10:17
  • Sorry, but I found a dupe. –  Mar 09 '20 at 10:21

2 Answers2

0

setState(updater[, callback]) is an async function:

https://facebook.github.io/react/docs/react-component.html#setstate

You can execute a function after setState is finishing using the second param callback like:

this.setState({
    instrumentCount: tempCount
}, () => {
    this.HandleDecrmenet(1)
});
0

i would do something like this

handleIncrement = (index) => new Promise(resolve => {
   const tempCount =  Object.assign([], this.state.instrumentCOunt);
  // increment the desired instrument
  tempCount[index] += 1;
  // update the state
  this.setState({
    instrumentCount: tempCount
  }, () => resolve(this.state.instrumentCount) ) ;
})

handleDecrement = (index) => new Promise(resolve => {
   const tempCount =  Object.assign([], this.state.instrumentCOunt);
  tempCount[index] -= 1;
  this.setState({
    instrumentCount: tempCount
  }, () => resolve(this.state.instrumentCount) ) ;
})


onClick={ ()=> {
   this.handleIncrement(1)
    .then(()=>  this.handleDecrement(0) )
}}

or using await

onClick={async ()=> {
  await  this.handleIncrement(1)
  this.handleDecrement(0) 
}}
vamshi krishna
  • 2,618
  • 1
  • 11
  • 18