(stateSet: T[] = [])
| 15 | } |
| 16 | |
| 17 | export default function useStateList<T>(stateSet: T[] = []): UseStateListReturn<T> { |
| 18 | const isMounted = useMountedState(); |
| 19 | const update = useUpdate(); |
| 20 | const index = useRef(0); |
| 21 | |
| 22 | // If new state list is shorter that before - switch to the last element |
| 23 | useUpdateEffect(() => { |
| 24 | if (stateSet.length <= index.current) { |
| 25 | index.current = stateSet.length - 1; |
| 26 | update(); |
| 27 | } |
| 28 | }, [stateSet.length]); |
| 29 | |
| 30 | const actions = useMemo( |
| 31 | () => ({ |
| 32 | next: () => actions.setStateAt(index.current + 1), |
| 33 | prev: () => actions.setStateAt(index.current - 1), |
| 34 | setStateAt: (newIndex: number) => { |
| 35 | // do nothing on unmounted component |
| 36 | if (!isMounted()) return; |
| 37 | |
| 38 | // do nothing on empty states list |
| 39 | if (!stateSet.length) return; |
| 40 | |
| 41 | // in case new index is equal current - do nothing |
| 42 | if (newIndex === index.current) return; |
| 43 | |
| 44 | // it gives the ability to travel through the left and right borders. |
| 45 | // 4ex: if list contains 5 elements, attempt to set index 9 will bring use to 5th element |
| 46 | // in case of negative index it will start counting from the right, so -17 will bring us to 4th element |
| 47 | index.current = |
| 48 | newIndex >= 0 |
| 49 | ? newIndex % stateSet.length |
| 50 | : stateSet.length + (newIndex % stateSet.length); |
| 51 | update(); |
| 52 | }, |
| 53 | setState: (state: T) => { |
| 54 | // do nothing on unmounted component |
| 55 | if (!isMounted()) return; |
| 56 | |
| 57 | const newIndex = stateSet.length ? stateSet.indexOf(state) : -1; |
| 58 | |
| 59 | if (newIndex === -1) { |
| 60 | throw new Error(`State '${state}' is not a valid state (does not exist in state list)`); |
| 61 | } |
| 62 | |
| 63 | index.current = newIndex; |
| 64 | update(); |
| 65 | }, |
| 66 | }), |
| 67 | [stateSet] |
| 68 | ); |
| 69 | |
| 70 | return { |
| 71 | state: stateSet[index.current], |
| 72 | currentIndex: index.current, |
| 73 | isFirst: index.current === 0, |
| 74 | isLast: index.current === stateSet.length - 1, |
searching dependent graphs…