# react 自定义 hook-useCountdown
# 场景:
服务于倒计时的场景,比如验证码发送的读秒倒计时。
# 简单实现
interface ICacheItem { | |
count: number; | |
timer: ReturnType<typeof setTimeout> | null; | |
setCount?: React.Dispatch<any>; | |
} | |
interface ICache { | |
[index: string]: ICacheItem; | |
} | |
const CACHE: ICache = {} | |
export const useCountdown = (taskName: string) => { | |
if (!CACHE[taskName]) { | |
CACHE[taskName] = { count: 0, timer: null } | |
} | |
const [count, setCount] = useState<number>(CACHE[taskName].count); | |
// 开始计时的方法 | |
const startCount = (num: number) => { | |
CACHE[taskName].count = num; | |
setCount(CACHE[taskName].count); | |
if (!CACHE[taskName].setCount) CACHE[taskName].setCount = setCount; | |
}; | |
// 停止计时 | |
const stopCount = () => { | |
if (CACHE[taskName].timer) { | |
clearTimeout(CACHE[taskName].timer!); | |
} | |
CACHE[taskName].count = 0; | |
if (CACHE[taskName].setCount && typeof (CACHE[taskName].setCount) === 'function') { | |
CACHE[taskName].setCount!(0); | |
} | |
CACHE[taskName].timer = null; | |
}; | |
useEffect(() => { | |
CACHE[taskName].timer = setTimeout(() => { | |
CACHE[taskName].count = count - 1; | |
if (count > 0) setCount(CACHE[taskName].count); | |
}, 1000); | |
}, [count]); | |
return { count, startCount, stopCount }; | |
} |
# 使用方法
如下是同一个组件中使用。
export default function CountDownTest() { | |
const {count,startCount,stopCount}=useCountdown('count') | |
return ( | |
<div> | |
<Button onClick={()=>{startCount(30)}} disabled={count>0}>{count>0?count:'30s 计时'}</Button> | |
<Button onClick={()=>{stopCount()}}>计时清零</Button> | |
</div> | |
); | |
} |
给 hooks 相同的 taskName 是可以获取到同样的 count,并且计时清零,也是可以在不同组件中实现