React倒计时若干种实现方法

html:

<Button type="link" onClick={HandleSubmit} disabled={disableFlag}>{linkText}</Button>
变量定义:
  const [disableFlag, setDisable] = useState<boolean>(false)
  const[linkText,setLinkText]=useState<string>('获取验证码')

1.原始版:

代码:

  let num =10
  let [num,setDisableSeconds]=useState<number>(10)
  const HandleSubmit = () => {
      setDisable(true);
     let x = setInterval(() => {
        if(num>0)
        {
          num=num-1;
        }
       setLinkText(num+'');
       if(num==0)
       {
         clearInterval(x);
         setDisable(false);
         setLinkText(linkText);
       }
      }, 1000);

  }

2.进阶版:

let newTimer =null;
  const [num, setDisableSeconds] = useState(10);
  const HandleSubmit = () => {
    setDisable(true);
    newTimer = setInterval(() => {
      if (num > 0) {
        setDisableSeconds((c) => c - 1);
      }
    }, 1000);
  }

  useEffect(()=>{
    if(disableFlag){
      setLinkText(num+'');
      if(num<0){
        clearInterval(newTimer);
        setDisable(false);
      }
    } else {
      setLinkText('获取验证码');
    }
  })

 第二版初看效果可以,但经过分析发现不行,原因在于由于页面渲染,造成useEffect方法不停地被调用,造成死循环。

经过分析,并改进,有了第三版:

let [start, setStart] = useState<boolean>(false);
useEffect(() => {
    let newTimer = null;
    if(start)
    {
      newTimer = setInterval(() => {
          if (num > 0) {
            setNumber((c) => c - 1);
          }
        }, 1000);
      if (disableFlag) {
        setLinkText(num + 'S后重试');
        if (num <= 0) {
          setDisable(false);
          console.log('111111')
        }
      } else {
        setLinkText('获取验证码');
    if(inputCode.length == 0) { setShowError1(true); } setStart(false); } return () => clearInterval(newTimer); } }, [num,disableFlag])

关键点在于,useEffect方法需要添加触发变量依赖:num及disableFlag,只有这2个变量发生变化时才能执行,经过验证发现效果ok。

posted @ 2022-06-28 13:11  Shapley  阅读(925)  评论(0编辑  收藏  举报