let [leftTime, setLeftTime] = useState(60);
const [codeStatus, setCodeStatus] = useState(true);
const runTime = () => {
const timer = setInterval(()=>{
setLeftTime(--leftTime);
if(leftTime <= 0){
clearInterval(timer);
setCodeStatus(true);
setDisabled(false);
}
},1000)
}
直接在定时器里 --leftTime 原地修改 state 变量,state 是 const 也不能直接改,而且闭包捕获了初始值,倒计时会错乱;同时用 let 只是表象,根本错误是同步修改 state 值、闭包陷阱。
优化后
import React from 'react';
import IconMap from 'components/IconMap.jsx';
import { LoginRule } from 'utils/rules';
import { Space } from 'antd';
const { Compact } = Space;
import { useState } from 'react';
const SmCodeLogin = ({form, FormItem, Input, Button}) => {
const handleSendCode = () => {
console.log('发送验证码');
setCodeStatus(false);
setLeftTime(60);
setDisabled(true);
runTime();
}
const [disabled, setDisabled] = useState(true);
const [leftTime, setLeftTime] = useState(60);
const [codeStatus, setCodeStatus] = useState(true);
const runTime = () => {
const timer = setInterval(()=>{
setLeftTime(prev=>{
if(prev <= 1){
clearInterval(timer);
setCodeStatus(true);
setDisabled(false);
return 0;
}
return prev-1;
});
},1000)
}
const checkMobile = async (e) => {
console.log(e.target.value,'e.target.value');
//const status = await form.validateFields(['mobile']);
//因为返回的promise2种状态采用trycatch处理
try{
const data = await form.validateFields(['mobile']);
console.log(data,'data');
setDisabled(false);
}catch(error){
console.log(error,'error');
setDisabled(true);
}
}
return (
<>
<FormItem
name="mobile"
rules={LoginRule.mobileRule}
hasFeedback={true}
>
<Input onChange={checkMobile} prefix={IconMap.mobile} placeholder="请输入手机号" />
</FormItem>
<FormItem
name="code"
rules={LoginRule.codeRule}
hasFeedback={true}
>
<Compact>
<Input
prefix={IconMap.code}
placeholder="请输入验证码"
// addonAfter={<Button onClick={handleSendCode}>发送验证码</Button>}
/>
<Button
disabled={disabled}
onClick={handleSendCode}
>
{codeStatus ? '发送验证码' : `${leftTime}秒后重新发送`}
</Button>
</Compact>
</FormItem>
</>
);
}
export default SmCodeLogin;
再次优化,解决定时器未销毁问题
import { useState, useRef, useEffect } from 'react';
const SmCodeLogin = ({form, FormItem, Input, Button}) => {
const handleSendCode = () => {
console.log('发送验证码');
setCodeStatus(false);
setLeftTime(60);
setDisabled(true);
runTime();
}
const [disabled, setDisabled] = useState(true);
const [leftTime, setLeftTime] = useState(60);
const [codeStatus, setCodeStatus] = useState(true);
const timerRef = useRef(null);
const runTime = () => {
// 防止重复点击多次开启定时器
if (timerRef.current) return;
setCodeStatus(false);
timerRef.current = setInterval(()=>{
setLeftTime(prev=>{
if(prev <= 1){
clearInterval(timerRef.current);
timerRef.current = null;
setCodeStatus(true);
setDisabled(false);
return 60;
}
return prev-1;
});
},1000)
}
// 组件卸载强制清定时器
useEffect(() => {
return () => {
if (timerRef.current) clearInterval(timerRef.current);
};
}, []);




