Skip to content

Instantly share code, notes, and snippets.

@IrvingArmenta
Created February 13, 2023 03:47
Show Gist options
  • Save IrvingArmenta/b96f29cc7024350c7f62bc67b264bb69 to your computer and use it in GitHub Desktop.
Save IrvingArmenta/b96f29cc7024350c7f62bc67b264bb69 to your computer and use it in GitHub Desktop.
useCycleState: hook for handling controlled queue states
import { useState } from 'react'
function useCycleState<T>(values: readonly T[]) {
const [currentIndex, setCurrentIndex] = useState(0)
const currentValue = values[currentIndex] as T
const nextAndPrev = (isPrev: boolean) => {
const valPlus = (currentIndex + 1) % values.length
let valMinus = (currentIndex - 1) % values.length
if (isPrev) {
return () => {
if (valMinus < 0) {
valMinus = values.length - 1
}
setCurrentIndex(valMinus)
}
} else {
return () => {
setCurrentIndex(valPlus)
}
}
}
const setIndex = (newIndex: number) => {
if (newIndex === 0) {
if (import.meta.env.DEV) {
console.error(
'useCycleState:',
`0 is not allowed as a new index, use a number in this range: 1 ~ ${values.length}`
)
}
return
}
if (newIndex === 1) {
newIndex = 0
}
if (values[newIndex]) {
setCurrentIndex(newIndex)
} else if (import.meta.env.DEV) {
console.error(
'useCycleState:',
`new index: ${newIndex} didn't return any value. make sure the newIndex number is in this range: 1 ~ ${values.length}`
)
}
}
return {
currentIndex: currentIndex + 1,
currentValue,
next: nextAndPrev(false),
prev: nextAndPrev(true),
setIndex,
}
}
export default useCycleState
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment