目录
一个自定义hook
的案例
实现一个倒计时
hooks
【需求介绍】
我们先简单的实现一个3秒倒计时的功能,就模仿我们常见的发短息验证码的功能。页面效果
【基础实现】:
功能比较简单,按钮点击的时候创建了一个定时器,然后时间到了就清除这个定时器。
app.jsx
中
MessageBtn.jsx
中
【改进】:
现在把
MessageBtn
中倒计时的逻辑写到一个自定义的hooks
里面。
自定义的useCountdown函数
把上面的一些逻辑抽取一下,
useCountdown
主要接受一个倒计时的时长,返回当前时间的状态,以及一个开始倒计时的函数
app.jsx
中
useCountDown.jsx
中1. 期望
useCountdown
支持两个函数,一个是在倒计时的时候调用,一个是在倒计时结束的时候调用。 【如图1】2.
start
函数用了useCallback
,因为我们不能保证用户的使用场景会不会出问题,所以我们包一下。 自定义hooks提供给别人的方法,最好用useCallback包裹一下,防止别人将该函数作为依赖项时出问题。【如图1】3. 这里
count
定义 0 有点歧义,0 不能准确的知道是一开始的 0 还是倒计时结束的 0,所以还需要加一个标志位来表示当前是结束的 0。使用useEffect
监听count
的变化,变化的时候触发对应的方法:let countDowning = useRef(false) 。【如图1】
【图1 】
4. 【提出问题】 那么,现在就有一个很严重的问题,
onEnd
和countdownCallBack
这两个函数是外部传入的,我们要不要把他放到我们自定义hook
的useEffect
依赖项里面呢我们不能保证外部传入的变量一定是一个被
useCallback
包裹的函数,那么肯定就不能放到useEffect
依赖项里面。如何解决这个问题呢?
答案就是使用
useRef
。使用别人提供的hooks返回的方法,如果需要将其作为依赖项,在不了解其方法是否用useCallback缓存的情况下,可以用useRef来接收后使用。【意图】:对于hooks所提供的方法“做最好的准备,做最坏的打算”。
【如图2(最终的写法)】
【图2】
自定义hooks,参数是一个函数,我们不能保证外部传入的变量一定是一个被useCallback包裹的函数,那么肯定就不能放到useEffect依赖项里面,所以需要useref包装一下。
MessageBtn.jsx
中
预期的使用是这样的,通过一个配置对象传入
countdownCallBack
函数和onEnd
useLatest.jsx中
源码【提问】:用useLastest和直接使用函数但是不把函数放进useEffect依赖中有什么区别?
【解答】:useEffect不写依赖 会产生闭包,拿到的函数是老的函数,useLastest可以拿到新的
比如
ahooks
里面的useLatest和useMemoizedFn的实现
在这里肯定也是看了很多介绍
useCallback
的文章了,推荐一下下面的文章how-to-use-memo-use-callback,这个是全英文的,掘金有翻译这篇文章的,「好文翻译」。
作者:既见君子
链接:https://juejin.cn/post/7271643757640007680
来源:稀土掘金