ReactHooks實現倒計時按鈕


學了一個禮拜的React,剛好看到了公司里的小程序項目,里面有個登錄獲取驗證碼倒計時的按鈕,就想用hooks實現下。

首先分析需求,組件內需要三個變量,分別存儲文字,按鈕狀態和倒計時時間。

const [content, setContent] = useState('獲取驗證碼')
const [btnDisabled, setBtnDisabled] = useState(false)
const [count, setCount] = useState(60)

設置一個button按鈕給點擊事件,按下后狀態變為disabled,開始定時器每秒減一,當時間為0時,清除定時器,重置會原來的狀態。

實現的邏輯並不復雜

首先我將時間的這部分抽離出來,寫成自定義hook。一開始我在函數最外部定義來存儲定時器,但后來發現如果同時調用兩個后,定時器是同一個。

import { useState, useEffect, useRef } from "react";
// let timerId
export default function useCountDown(initCount = 60) {
  const [count, setCount] = useState(() => initCount)
  const timerId = useRef(null)

  // 設置清除定時器,避免count還未為0時,組件已被Unmount
  useEffect(() => {
    return () => {
      clearInterval(timerId.current)
    }
  }, [])

  // 監聽count的變化 
  useEffect(() => {
    if (count === 0) {
      clearInterval(timerId.current)
      setCount(60)
    }
  }, [count])
  // 定義定時器,每秒減一
  function run () {
    timerId.current = setInterval(() => {
      setCount(pre => pre - 1)
    }, 100)
  }
  return {count, run}
}
View Code

這里我還用到了memo,可以減少不必要的渲染,我還遇到了一個問題,我想使用useCallback存儲最開始的數據。但是雖然log出的數據是改變了,但並沒有在頁面上重新渲染。這可能是React中回調觸發渲染有關。還是得繼續學習。

import { memo, useCallback } from "react";
import { useState, useEffect } from "react";
import useCountDown from "./useCountDown";
export default memo(function CountDownButton() {
  const [content, setContent] = useState('獲取驗證碼')
  const [btnDisabled, setBtnDisabled] = useState(false)
  const {count, run} = useCountDown()
  
  useEffect(() => {
    if (btnDisabled) {
      setContent(`${count}秒后`)
    }
    if (count === 0) {
      btnStatusReset()
    }
  }, [count])
  // 按鈕點擊事件
  function handleBtnClick () {
    setBtnDisabled(true)
    setContent(`${count}秒后`)
    run()
  }
  // 重置按鈕狀態
  // const btnStatusReset = useCallback(() => {
  //   setContent('獲取驗證碼')
  //   setBtnDisabled(pre => pre)
  //   console.log(content, btnDisabled)
  // }, [])
  const btnStatusReset = () => {
    setContent('獲取驗證碼')
    setBtnDisabled(false)
  }
  return (
    <>
      <input type="text" />
      <button disabled={btnDisabled} onClick={handleBtnClick}>{content}</button>
    </>
  )
})

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM