skip to Main Content

I’m aware that useState is asynchronous. I’m attempting to have a toggle button that will add one point to score if itemSelected is true and remove one point from score if itemSelected is false. The issue here of course is that due to the asynchronous nature of setState there is a delay so the code below doesn’t work properly.

My question: How do I get around this issue?

const [score, setScore] = useState(0); 

const [itemSelected, setItemSelected] = useState(false);

const toggleItem1 = () => {
setItemSelected(!itemSelected, setCallback())
}

const setCallback = () => {

if (score < 5 && itemSelected ){ 
setScore(score + 1) 
}
if (score < 5 && !itemSelected ){ 
setScore(score - 1) 
}
if (score == 5){
completeSection()
}
}

2

Answers


  1. You can use useRef hook to store the score like this

    const score = useRef(0)
    const itemSelected = useRef(false)
    
    const toggleItem1 =() => {
      itemSelected.current = !itemSelected.current
      setCallback()
    }
    
    const setCallback() => {
      if (score.current < 5 && itemSelected.current ){ 
        score.current +=1  
      }
      if (score.current < 5 && !itemSelected.current ){ 
        score.current -=1   
      }
      if (score.current == 5){
        completeSection()
      }
    }
    
    Login or Signup to reply.
  2. The real issue is that you are trying everything in one function. You are mutating the state and reading it in the same place.
    I would put a controller, like useEffect, useCallback or useMemo to read the state, and if it satisfies a condition, it would trigger a function, like this:

    const [score, setScore] = useState(0); 
    
    const [itemSelected, setItemSelected] = useState(false);
    
    useEffect(()=>{
    if(score === 5){
    completeSection()}
    }
    ,[score])
    
    const toggleItem1 = () => {
    setItemSelected(!itemSelected, setCallback())
    }
    
    
    const setCallback = () => {
    
    if (score < 5 && itemSelected ){ 
    setScore(score + 1) 
    }
    if (score < 5 && !itemSelected ){ 
    setScore(score - 1) 
    }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search