A Custom Hook for Quickly Changing Numbers (feat. React)
I built a custom hook that quickly changes a number until it reaches a target value.
code
import { useEffect, useState } from 'react';
type useRollingNumberProps = {
target: number;
min?: number;
max?: number;
};
const useRollingNumber = ({
target,
min = 0,
max = 100,
}: useRollingNumberProps) => {
const [animatedNumber, setAnimatedNumber] = useState(0); // the number to display on screen
useEffect(() => {
if (animatedNumber === 0) return setAnimatedNumber(target); // set the initial value
if (animatedNumber === target) return; // change complete
// change the number only at a rate visible to the human eye
requestAnimationFrame(() => {
const increment = target > animatedNumber ? 1 : -1; // check whether to increase or decrease the number
setAnimatedNumber((prev) => {
if (increment) return prev + increment > max ? max : prev + increment; // when increasing, only go up to max
return prev + increment <= min ? min : prev + increment; // when decreasing, only go down to min
});
});
}, [target, min, max, animatedNumber]);
return {
animatedNumber,
};
};
export default useRollingNumber;
usage
const Info = () => {
const { experiencePercent } = useMainCharacterStore(); // // increase or decrease by the experiencePercent value
const { animatedNumber } = useRollingNumber({ target: experiencePercent, min: 0, max: 100 }); // the target is max 0, max 100
return (
<div className='info'>
<div className='gauge'>
<span className='graph' style={{ width: `${animatedNumber}%` }} />
<strong className='percent'>{animatedNumber}%</strong>
</div>
</div>
);
};
export default Info;
20240326
Leave a comment