'repeat step algorithm react javascript

I want to make a repeated array like this

 1->2->3->1->2->3.....

 const [current,setCurrent] = useState(0);
 const [direction,setDirection] = useState()
 const prevCurrent = usePrevious(current)
 const maxData = 3;
 function handler(val){
    if(val==='plus'){
      current !== maxData ? setCurrent(prev=>prev+1):setCurrent(0)
    }else{
      current !== 0 ? setCurrent(prev=>prev-1):setCurrent(maxData)
    }
 }
 useEffect(()=>{
   if(current>prev){
     setDirection('next')
   } else{
     setDirection('prev')
   }
 },[current])
 
 return <div>
          <button onClick={()=>handler('plus')}>+</button>
          <button onClick={()=>handler('min')}>-</button>
          <span>{direction}</span>
        </div>

In this case, I always want to repeat my current, example if the new current is 2 and prev current is 1 then the direction will be next, but when the current is the last step and the current will set to 0, but the direction will be set to 'prev' because current < prev, but I want my direction still set to next.

Is there some algorithm to fix this one?



Solution 1:[1]

I think I understand what you are looking for. If so, then you should be able to simply call setDirection from your handler, something like this:

const {useState, useEffect} = React;

const MyComponent = () => {
  const [current, setCurrent] = useState (0)
  const [direction, setDirection] = useState ('?')
  const maxData = 3
  function handler (val){
    if (val === 'plus'){
      setDirection ('next')
      current !== maxData ? setCurrent (prev => prev + 1) : setCurrent (0)
    } else {
      setDirection ('prev')
      current !== 0 ? setCurrent (prev => prev - 1): setCurrent (maxData)
    }
  }
  return <div>
    <button onClick={() => handler ('plus')}>+</button>
    <button onClick={() => handler ('min')}>-</button>
    <p>{current} ({direction})</p>
  </div>
}

ReactDOM.render(
  <MyComponent />,
  document.getElementById("react")
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

But I think you can also clean this up more doing two things. First, skip the "plus" and "min" strings, and use +1 and -1 instead. Second, keep an array of values that you want to loop, and make current track the index into that array, using a true modulus function to wrap around to the beginning/end of the array.. Note that the remainder operator - % is not a true modulus, as it doesn't work correctly with negative operands.

const {useState, useEffect} = React;
const mod = (n, m) => ((n % m) + m) % m

const MyComponent = () => {
  const [current, setCurrent] = useState (0)
  const [direction, setDirection] = useState ('?')
  
  const options = [1, 2, 3]
  
  const handler = (delta) => {
    setCurrent ((prev) => mod (prev + delta,  options .length))
    setDirection (() => delta > 0 ? 'next' : 'prev') 
    console .log ({delta, current, option: options[current]})
  }

  return <div>
    <button onClick = {() => handler (+1)}>+</button>
    <button onClick = {() => handler (-1)}>-</button>
    <p>{options [current]} ({direction})</p>
  </div>
}

ReactDOM.render(
  <MyComponent />,
  document.getElementById("react")
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Scott Sauyet