持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情
今天开始一起学习分享 ahooks 的源码
ahooks是阿里巴巴出品的一套高质量可靠的 React Hooks 库
今天分享 第25个 hooks-useTimeout
useTimeout
useTimeout 的作用是什么
useTimeout 的作用是 一个可以处理 setTimeout 计时器函数的 Hook。
接下来 看下 API
API
useTimeout(
fn: () => void,
delay?: number | null
): fn: () => void;
Params
一共有3个参数
第1个参数是fn,表示要定时调用的函数
第2个是delay,表示间隔时间,当设置值为 undefined
时会停止计时器
参数 | 说明 | 类型 |
---|---|---|
fn | 待执行函数 | () => void |
delay | 定时时间(单位为毫秒),支持动态变化,,当取值为 undefined 时会停止计时器 | number | undefined |
Result
参数 | 说明 | 类型 |
---|---|---|
clearTimeout | 清除定时器 | () => void |
接下来 看下 用法
基础用法
每1000ms,执行一次
import React, { useState } from 'react';
import { useTimeout } from 'ahooks';
export default () => {
const [state, setState] = useState(1);
useTimeout(() => {
setState(state + 1);
}, 3000);
return <div>{state}</div>;
};
3000ms 后执行一次
进阶使用
动态修改 delay 以实现定时器间隔变化与暂停。
import React, { useState } from 'react';
import { useTimeout } from 'ahooks';
export default () => {
const [count, setCount] = useState(0);
const [delay, setDelay] = useState<number | undefined>(1000);
const clear = useTimeout(() => {
setCount(count + 1);
}, delay);
return (
<div>
<p> count: {count} </p>
<p style={{ marginTop: 16 }}> Delay: {delay} </p>
<button onClick={() => setDelay((t) => (!!t ? t + 1000 : 1000))} style={{ marginRight: 8 }}>
Delay + 1000
</button>
<button
style={{ marginRight: 8 }}
onClick={() => {
setDelay(1000);
}}
>
reset Delay
</button>
<button onClick={clear}>clear</button>
</div>
);
};
接下来一起看下 源码
源码
1.首先定义传入参数的类型
fn: () => void, delay: number | undefined
2.使用useRef定义一个定时器
const timerRef = useRef<NodeJS.Timer | null>(null);
3.返回清除定时器的函数,在useCallback中判断是否存在定时器,如果存在定时器,则使用clearInterval清除定时器
const clear = useCallback(() => {
if (timerRef.current) {
clearTimeout(timerRef.current);
}
}, []);
4.使用useLatest包裹传入的函数。判断delay是否存在和小于零,是的话则直接return.如果immediate为true,则直接执行函数。否则的话,在指定时间执行该函数,并清除定时器
useEffect(() => {
if (!isNumber(delay) || delay < 0) {
return;
}
timerRef.current = setTimeout(() => {
fnRef.current();
}, delay);
return () => {
if (timerRef.current) {
clearTimeout(timerRef.current);
}
};
}, [delay]);