亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

setInterval 刷新應用而不是更新狀態

setInterval 刷新應用而不是更新狀態

慕萊塢森 2022-05-26 11:09:21
我正在用 編寫倒計時Expo。我正在使用functional components,所以我state是通過 React 的useState鉤子處理的。let [state, setState] = useState({    secondsLeft: 25,    started: false,});如果我按 aButton它確實會觸發此功能:let onPressHandler = (): void => {    if(!state.started) {        setState({...state, started: true});        setInterval(()=> {            setState({...state, secondsLeft: state.secondsLeft - 1});            console.log(state.secondsLeft);        }, 1000);    }}問題是每 1000 毫秒 Expo 刷新應用程序而不是更新狀態。
查看完整描述

1 回答

?
眼眸繁星

TA貢獻1873條經驗 獲得超9個贊

它更新狀態,但它使用陳舊狀態來執行此操作。一旦間隔開始,回調中的state變量將永遠不會改變。setInterval


相反,請使用狀態更新函數的 setter 形式,因此您始終使用當時的狀態:


let onPressHandler = (): void => {

    if(!state.started) {

        setState({...state, started: true});

        setInterval(()=> {

            setState(currentState => {

                const newState = {...currentState, secondsLeft: currentState.secondsLeft - 1};

                console.log(newState.secondsLeft);

                return newState;

            });

        }, 1000);

    }

};

沒有以下內容會更簡潔console.log:


let onPressHandler = (): void => {

    if(!state.started) {

        setState({...state, started: true});

        setInterval(()=> {

            setState(currentState => {...currentState, secondsLeft: currentState.secondsLeft - 1});

        }, 1000);

    }

};

單獨說明:如果您有彼此獨立更新的狀態項,最佳實踐是為它們使用單獨的狀態變量。此外,由于它們在您的函數中是常量,因此最好將它們聲明為const. 像這樣:


const [secondsLeft, setSecondsLeft] = useState(25);

const [started, setStarted] = useState(false);


// ...

let onPressHandler = (): void => {

    if(!started) {

        setStarted(true);

        setInterval(()=> {

            setSecondsLeft(seconds => seconds - 1);

        }, 1000);

    }

};

此外,由于您不能完全依賴setInterval精確,我建議存儲您的停止時間(“現在”加上 25 秒)并重新計算每次還剩多少秒:


let onPressHandler = (): void => {

    const stopTime = Date.now() + (DURATION * 1000);

    setStarted(true);

    setSecondsLeft(DURATION);

    const timer = setInterval(()=> {

        const left = Math.round((stopTime - Date.now()) / 1000);

        if (left <= 0) {

            clearInterval(timer);

            setStarted(false);

        } else {

            setSecondsLeft(left);

        }

    }, 1000);

};

現場示例(帶有停止邏輯):

const {useState} = React;


const Example = () => {

    const DURATION = 25; // seconds

    const [started, setStarted] = useState(false);

    const [secondsLeft, setSecondsLeft] = useState(0);


    if (started) {

        return <div>Seconds left: {secondsLeft}</div>;

    }


    let onPressHandler = ()/*: void*/ => {

        const stopTime = Date.now() + (DURATION * 1000);

        setStarted(true);

        setSecondsLeft(DURATION);

        const timer = setInterval(()=> {

            const left = Math.round((stopTime - Date.now()) / 1000);

            if (left <= 0) {

                clearInterval(timer);

                setStarted(false);

            } else {

                setSecondsLeft(left);

            }

        }, 1000);

    };

    return (

        <input

            type="button"

            onClick={onPressHandler}

            value="Start"

        />

    );

};


ReactDOM.render(<Example />, document.getElementById("root"));

<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>


查看完整回答
反對 回復 2022-05-26
  • 1 回答
  • 0 關注
  • 214 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號