-1

I am trying to create a state which will keep track of a list by the states value. It increases or decreases by 1. However, it does not work exactly how I am expecting it to. I am using the up and down arrow keys to increment or decrement the value, and whenever I "change direction" it updates the state once more in the previous direction before it goes the correct way. I provide an image with console logs to make it clear what I mean.

console-log

I will also provide some code of course.

export const SearchBar = (props) => {
...
const [currentItem, setCurrentItem] = useState(0);
...
...
const handleKeyPress = (e) => {
    const keyPressed = e.key;
    if (keyPressed === "ArrowDown") {
      setCurrentItem(currentItem +1);
      
    } else if (keyPressed === "ArrowUp" && currentItem >= 0) {
      setCurrentItem(currentItem -1);
      
    } else if (keyPressed === "Enter") {
      dispatch(setSearchTerm(''));
      setCurrentItem(0);

    }
  }

}

  • Where in the code are you logging the new state? – Andy Dec 09 '21 at 08:38
  • Directly after "setCurrentItem" which seems to be another mistake by me. I have now been watching the state in chrome dev-tools and notice that the state actually changes as I am expecting it too, but sometimes it delays, I guess enough for the console.log to print out the incorrect value. aargh, javascript :) – Jonathan Manner Dec 09 '21 at 08:40
  • 1
    This isn't a JS issue but more to do with how React updates state which generally is done asynchronously and in batches (mostly). You can use [`useEffect` to execute code when state](https://reactjs.org/docs/hooks-effect.html) updates. For example: `useEffect(() => console.log(currentItem), [currentItem]);` – Andy Dec 09 '21 at 08:49
  • PS there's no standard to how dev consoles are written. [Some browsers](https://stackoverflow.com/questions/4057440/is-chromes-javascript-console-lazy-about-evaluating-arrays) tend to log things differently to others. – Andy Dec 09 '21 at 08:52
  • 1
    [Even more reading](https://reactjs.org/docs/state-and-lifecycle.html). – Andy Dec 09 '21 at 08:54

1 Answers1

1

When mutating states based on the previous states you should make use of the useState callback. Instead of:

setCurrentItem(currentItem + 1)

try:

setCurrentItem((prevState) => prevState + 1)

This will ensure that you always get the latest previous state when updating it.

Martin Z
  • 238
  • 2
  • 5