3

I have the following states:

let [currentMonth, setCurrentMonth] = useState(new Date().getMonth());
const [checkIn_month, setCheckInMonth] = useState(null);

I have an click event listener assigned directly to JSX's element tbody. Using event delegation to click on the td elements.

And in the following function if i click on a day that is in the previous month i need to decrement the currentMonth state and after that to set the new value of currentMonth in the setCheckInMonth state.

The problem is:

When i use the setCheckInMonth(currentMonth) state hook it gives the old value, not the new one.

let [currentMonth, setCurrentMonth] = useState(new Date().getMonth());
const [checkIn_month, setCheckInMonth] = useState(null);

const selectDate = e => {

 if (e.target.tagName === 'TD') {

   if (e.target.classList.contains('previous-month-day')) {
    setCurrentMonth(currentMonth => currentMonth - 1);
    setCheckInMonth(currentMonth);
   }
  }
}

What if i do something like this:

setCurrentMonth(currentMonth => currentMonth - 1);
setCheckInMonth(currentMonth - 1);

Is this a correct way of doing it ?

2 Answers2

2

setState() is asynchronous. It doesn't immediately mutate(update) the object. So doing this -

setCurrentMonth(currentMonth => currentMonth - 1);

doesn't mean that currentMonth has the updated value that you can use immediately in the next line.

What you can do is -

const newCurrentMonth = currentMonth - 1;
// now use this newCurrentMonth to update the state.
setCurrentMonth(newCurrentMonth );
setCheckInMonth(newCurrentMonth );
Arnab Roy
  • 619
  • 5
  • 16
  • Ok so the last answer that i post it in the question is correct ? `setCurrentMonth(currentMonth => currentMonth - 1);` `setCheckInMonth(currentMonth - 1);` –  Jan 13 '20 at 07:14
  • @grecdev that can't be said for sure. As I mentioned in my answer - `setState` is async. So if in some cases currentMonth is updated right away, then `checkInMonth` would have wrong value. This case is very highly unlikely. But it can happen theoratically. So I would not suggest that approach. – Arnab Roy Jan 13 '20 at 07:34
0

If you want to update checkIn_month using the current value of currentMonth, you can't rely on currentMonth's value being updated immediately, as setState calls are asynchronous. You can instead move your call to setCheckInMonth within the callback passed to setCurrentMonth so that you have access to the current value of currentMonth.

For example:

setCurrentMonth(currentMonth => {
    const newCurrentMonth = currentMonth - 1;
    setCheckInMonth(newCurrentMonth);
    return newCurrentMonth;
});
Henry Woody
  • 14,024
  • 7
  • 39
  • 56