无法使用clearTimeout停止setTimeout函数,因为值由于某种原因为null

问题描述

在我的本机应用程序中,我试图使用setTimeout停止clearTimeout。我将setTimeout的实例保存在全局变量中。

let timeoutId:any = null;

    const doOtp = ()=>{
        if(canSendOtp) {
            setCanSendOtp(false);

            timeoutId = setTimeout(() => { // it has here a numeric value
                showNotificationMessage("You can request OTP again")
                setCanSendOtp(true)
            },SEND_OTP_TIME_CONSTRAINTS)

           // rest of doOtp logic
        }
        else {
            showNotificationMessage("Please wait " + (SEND_OTP_TIME_CONSTRAINTS / 1000) + " seconds before trying again")
        }
    }

然后,当我想使用clearTimeout停止setTimeout时,我看到timeoutId的值为null。我不明白为什么会这样。

const doLogin = () => {
issuetoken(LOGIN_GRANT_TYPE,LOGIN_CLIENT_ID,LOGIN_CLIENT_SECRET,phoneNumber,otp)
    .then(res => { 
        
        console.log('timeoutId !== null' + timeoutId !== null)
        if(timeoutId !== null) { // value here is null - why?
            clearTimeout(timeoutId)
        }

        store().dispatch(setTokenValidity(res))
    })
    .catch(err => {
        showNotificationMessage('Error,something went wrong check logs.')
        console.log("issuetoken error: " + JSON.stringify(err))
    });

}

解决方法

问题

setCanSendOtp(true)更新您的状态,这会将您的超时再次初始化为空。

解决方案

将超时设置为参考。 Ref值在重新渲染和状态更新之间保持不变。

const timeoutId:any = React.useRef(null);

const doOtp = ()=>{
        if(canSendOtp) {
            setCanSendOtp(false);

            timeoutId.current = setTimeout(() => { // it has here a numeric value
                showNotificationMessage("You can request OTP again")
                setCanSendOtp(true)
            },SEND_OTP_TIME_CONSTRAINTS)

           // rest of doOtp logic
        }
        else {
            showNotificationMessage("Please wait " + (SEND_OTP_TIME_CONSTRAINTS / 1000) + " seconds before trying again")
        }
    }

const doLogin = () => {
issueToken(LOGIN_GRANT_TYPE,LOGIN_CLIENT_ID,LOGIN_CLIENT_SECRET,phoneNumber,otp)
    .then(res => { 
        
        if(timeoutId.current !== null) {
            clearTimeout(timeoutId.current)
        }

        store().dispatch(setTokenValidity(res))
    })
    .catch(err => {
        showNotificationMessage('Error,something went wrong check logs.')
        console.log("issueToken error: " + JSON.stringify(err))
    });