I have 3 components with different numbers. What I want is something like this:
What should I consider? here is my trial. I would appreciate it if you could give me some points to consider.
https://jsfiddle.net/pizza_hamburger_chicken/ptav9wyg/7/
const {useState, useEffect} = React;
const AnimationNumber = ({ number }) => {
// ------------ useRef
// ------------ useState
const [numberForCount, setNumberForCount] = useState(0);
// ------------ useEffect
useEffect(() => {
let count = 0;
const id = setInterval(() => {
if (count >= number) {
clearInterval(id);
} else {
console.log(++count);
setNumberForCount(count);
}
}, 0.01);
}, []);
// ------------ methods
// ------------ event methods
// ------------ api methods
return (
<div
data-target={number}
>
<strong>
<span>{numberForCount}</span>
</strong>
</div>
);
};
function Example() {
return (
<div>
<AnimationNumber number={700} />
<AnimationNumber number={100} />
<AnimationNumber number={470} />
</div>
);
}
ReactDOM.render( <Example />, document.getElementById('root') );
const {useState, useEffect, useCallback} = React;
const animationSpeed = 7
const useCounter = (ending, start) => {
const [count, setCount] = useState(0)
const ratio = parseInt(ending/100)
useEffect(() => {
if (start) {
const interval = setInterval(() => {
if (count < ending) {
setCount(count+ratio > ending ? ending : count+ratio)
} else {
clearInterval(interval)
}
}, animationSpeed)
return () => clearInterval(interval)
}
}, [count, start])
return count
}
const AnimationNumber = ({ number , start}) => {
let count = useCounter(number, start)
return (
<div
data-target={number}
>
<strong>
<span>{count}</span>
</strong>
</div>
);
};
function Example() {
const [starter, setStarter] = useState(false)
const start = useCallback(() => {
setStarter(true)
}, [])
return (
<div>
<button onClick={start}>Start!</button>
<AnimationNumber number={100} start={starter} />
<AnimationNumber number={1500} start={starter} />
<AnimationNumber number={5000} start={starter} />
<AnimationNumber number={590} start={starter} />
<AnimationNumber number={1024} start={starter} />
<AnimationNumber number={3600} start={starter} />
</div>
);
}
ReactDOM.render( <Example />, document.getElementById('root') );
If the component's only purpose is to display this number then you could avoid state altogether and use a ref and update the span's innerText directly
const {useState, useRef, useEffect} = React;
const _period = 10000
const AnimationNumber = ({ number, intervalTime=10, period=_period }) => {
const countEl = useRef(null);
const count = useRef(0);
useEffect(() => {
const interval = setInterval(() => {
if (count.current < number) {
const amountPerRun = number * (intervalTime/period);
count.current += amountPerRun;
countEl.current.innerText = Math.min(number, Math.floor(count.current));
return;
}
clearInterval(interval)
console.log('done!', number);
}, intervalTime);
return () => clearInterval(interval)
}, []);
return (
<div>
<strong>
<span ref={countEl} />
</strong>
</div>
);
};
function Example() {
return (
<div>
<AnimationNumber number={700} />
<AnimationNumber number={100} />
<AnimationNumber number={470} />
</div>
);
}
ReactDOM.render( <Example />, document.getElementById('root'));