反应倒数计时器

时间:2021-07-19 07:41:35

标签: javascript reactjs typescript react-native

我有一个倒数计时器片段,如下所示:

const [remainingTime, setRemainingTime]: [number, Dispatch<SetStateAction<number>>] = useState<number>(0);
const [updatedTime, setUpdatedTime]: [number, Dispatch<SetStateAction<number>>] = useState<number>(0);
const referenceTime = useRef<number>(0); // new Date().getTime()
const intervalRef = useRef<number>(updatedTime);

const decreaseTime = () =>
        setUpdatedTime((prevState) => {
            if (prevState > 1) {
                    return parseFloat(((updatedTime * 1000 + referenceTime.current - Date.now()) / 1000).toFixed(0));
            } else {
                setRemainingTime(0);
                return 0;
            }
        });
    
    useEffect(() => {
        if (remainingTime > 0) {
            intervalRef.current = setInterval(decreaseTime, 1000) as unknown as number;
        }

        return () => clearInterval(intervalRef.current);
}, [remainingTime]);

一切正常,直到我想为其添加增量和减量选项。有必要使用 Date.now() 和 referenceTime,因为该模块用于 react-native 并且它必须在后台模式下工作,所以我应该在哪里更改某些内容以正确升级状态。我尝试了以下解决方案:

setUpdatedTime((prevState) => prevState + 10)

setUpdatedTime((prevState) => updatedTime + 10)

更新: https://codesandbox.io/s/react-countdown-timer-lr9sb

感谢您的帮助。 :)

1 个答案:

答案 0 :(得分:0)

如果有人处于相同情况的解决方案: https://codesandbox.io/s/react-countdown-timer-lr9sb?file=/src/App.tsx

const [remainingTime, setRemainingTime]: [number, Dispatch<SetStateAction<number>>] = useState<number>(0);
const [updatedTime, setUpdatedTime]: [number, Dispatch<SetStateAction<number>>] = useState<number>(0);
const referenceTime = useRef<number>(0); // new Date().getTime()
const intervalRef = useRef<number>(updatedTime);

const decreaseTime = () =>
        setUpdatedTime((prevState) => {
            const difference = parseFloat((Date.now() - referenceTime.current - 1000).toFixed(0))
            if (prevState > 1) {
                    return parseFloat(((prevState * 1000 + referenceTime.current - Date.now() + (difference)) / 1000).toFixed(0));
            } else {
                setRemainingTime(0);
                return 0;
            }
        });
    
    useEffect(() => {
        if (remainingTime > 0) {
            intervalRef.current = setInterval(decreaseTime, 1000) as unknown as number;
        }

        return () => clearInterval(intervalRef.current);
}, [remainingTime]);