@supunlakmal/hooks
Version:
A collection of reusable React hooks
47 lines • 2.29 kB
JavaScript
import { useState, useCallback } from 'react';
/**
* @name useEnum
* @description - Hook that manages state constrained to the values of a given enum object.
* Allows cycling through enum values.
*
* @template T The enum object type.
* @param {T} enumObject The enum object itself (e.g., MyEnum).
* @param {T[keyof T]} initialValue The initial enum value.
* @returns {[T[keyof T], { set: (value: T[keyof T]) => void; next: () => void; prev: () => void; }]} A tuple containing the current enum value and an object with functions to set, go to the next, or go to the previous enum value.
* @throws If the initialValue is not a valid value within the enumObject.
*
* @example
* enum Direction { North, East, South, West }
* const [direction, { set: setDirection, next, prev }] = useEnum(Direction, Direction.North);
*
* next(); // direction becomes Direction.East
* prev(); // direction becomes Direction.North again
* setDirection(Direction.South); // direction becomes Direction.South
*/
export const useEnum = (enumObject, initialValue) => {
// Get both string and numeric keys/values, filter duplicates for standard enums
const enumValues = Object.values(enumObject).filter((v) => typeof v === 'number' || typeof enumObject[v] !== 'number');
if (!enumValues.includes(initialValue)) {
throw new Error('useEnum initialValue must be a valid value from the enumObject.');
}
const [currentValue, setCurrentValue] = useState(initialValue);
const currentIndex = enumValues.indexOf(currentValue);
const set = useCallback((value) => {
if (enumValues.includes(value)) {
setCurrentValue(value);
}
else {
console.warn(`useEnum set: Provided value is not a valid member of the enum.`);
}
}, [enumValues]);
const next = useCallback(() => {
const nextIndex = (currentIndex + 1) % enumValues.length;
setCurrentValue(enumValues[nextIndex]);
}, [currentIndex, enumValues]);
const prev = useCallback(() => {
const prevIndex = (currentIndex - 1 + enumValues.length) % enumValues.length;
setCurrentValue(enumValues[prevIndex]);
}, [currentIndex, enumValues]);
return [currentValue, { set, next, prev }];
};
//# sourceMappingURL=useEnum.js.map