zoukankan      html  css  js  c++  java
  • 点击就产生60秒倒计时的按钮->点击后就会执行某操作,立刻开启倒计时x秒,倒计时结束才能再次能够点击。

    点击就产生60秒倒计时的按钮

    点击后就会执行某操作,立刻开启倒计时x秒,倒计时结束才能再次能够点击。

    export function subscribeInterval(ms, task) {
        const handle = setInterval(task, ms);
        return () => clearInterval(handle);
    }
    
    export const useInterval = (ms, task) => useEffect(() => subscribeInterval(ms, task), []);
    
    
    
    export function CountDownButton({countDown, normalText, waitText, task, ...props}) {
        const [count, setCount] = useState(0);
        const [isWait, setIsWait] = useState(false);
        const timer = useRef(-1);
        // const wait = ()=>{
        //     clearInterval(timer.current);
        //     timer.current = setInterval(()=>{
        //         setCount(count => count -1);
        //         if(count <= 0){
        //             setIsWait(false);
        //             clearInterval(timer.current);
        //             setCount(countDown);
        //             console.log(count);
        //             console.log("??");
        //         }
        //     }, 1000);
        // };
        useEffect(()=>{
            clearInterval(timer.current);
            timer.current = setInterval(()=>{
                setCount(count => count -1);
                console.log(count)
                if(count == 0){
                    setIsWait(false);
                    clearInterval(timer.current);
                    console.log(count);
                    console.log("??");
                }
    
            }, 1000);
        }, [count]);
        // useEffect(()=>{
        //     console.log("111");
        //     setCount(countDown);
        // },[countDown])
        return <>
            <Button type="primary" disabled={isWait} onClick={() => {
                task();
                setIsWait(true);
                setCount(countDown);
            }} {...props}>{isWait ?count + "秒后" + waitText : normalText}</Button>
        </>
    }
    

    第二天想起来,这段代码显然是有问题的,虽然它的效果看着挺正常的……它现在的效果是:count改变->useEffect内部执行清除定时器,然后又创建定时器,然后对count进行-1操作->useEffect执行,清除刚刚的定时器,又创建新的定时器……

    所有它其实一直是创建定时器,-1,清除刚刚的定时器,创建新的定时器,-1,清除,创建……这样虽然基本上是1秒减1,但是其实完全不是我想要的效果。

    后来想了一下,应该是开始等待isWait为true时,启动计时器,在计时器进行了countDown次操作后,清除计时器。同时在useEffect执行的那一刻,就形成了一个闭包,此时在计时器里面的count都是形成闭包时的数据,也就是计时器每次运行时,count还是一开始的count(但是因为是setCount(count => count-1)这样写的,外部的count是正常地进行着1秒减1的操作的。所以我加了一个局部变量,-1操作的次数都用它来记录,当达到倒计时要求的次数时,就可以终止倒计时了。可能有点冗余,但是应该是对的哈哈:

    useEffect(()=>{
                if(isWait === true){
                    clearInterval(timer.current);
                    let countTime = 0;
                    timer.current = setInterval(()=>{
                        setCount(count => count -1);
                        countTime ++;
                        if(countTime === countDown){
                            setIsWait(false);
                            clearInterval(timer.current);
                        }
                    }, 1000);
                }
            }, [isWait]);
    
  • 相关阅读:
    IP地址和MAC地址,以及arp攻击
    可爱的老婆
    win7 homebasic下,.net2008 连接oracle,提示错误OCIEnvCreate 失败,返回代码为 1,但错误消息文本不可用
    检讨
    数据库索引
    PB调用C#编写的DLL
    用c#开发可供PB调用的COM组件
    关于excel取消科学计数法的问题
    按键码对照
    JSONP学习资料
  • 原文地址:https://www.cnblogs.com/peekapoooo/p/14248064.html
Copyright © 2011-2022 走看看