众所周知,不会写BUG的不是好程序员(懂的都懂哈)
我说React比Vue难使没意见吧
想必大家肯定见过发送验证码的场景吧,他让你过一段时间才能重新发送
那我就写一下这个场景,来看看我的想法
- 首先我整一个Login组件(我都是用 function component)
- 然后我给他整一个状态 time
- 当我点击发送验证码的时候,让 time 为60
- 并且设置一个定时器,让 time 每过一秒减 1 ,当 time 等于 0 的时候 clear 定时器
- perfect!!!
好的,接下来看代码实现(贴的是关键代码)
const [time, setTime] = useState(0)
const sendCode = () => {
setTime(60)
let timer: NodeJS.Timer
timer = setInterval(() => {
if (time === 0) {
clearInterval(timer)
}
setTime(time - 1)
}, 1000)
//TODO
}
<div className="flex">
<input id='code' type={'text'} className="outline-none flex-1 text-lg" />
<div onClick={() => { !time && sendCode() }}>{time ? time + 's 后可重新发送' : '发送验证码'}</div>
</div>
下面来看一下结果
- 点击发送之后,先是这个效果
- 一秒之后
我Interval呢???
这就是 hooks 的经典问题了,闭包缺陷
这里直接不说太深入
简单说就是 setTime 给 time 赋值会创建新的变量,相当于 setTime(60) 的确修改了 time ,在视图上也显示了,但是我定时器里面的 time 还是老的 time ,所以老的time是 0 一上来就给 timer 清除了,随后调用了 setTime(time - 1) ,实质上就是调用 setTIme(-1) ,所以随后你会看到的是 -1