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