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

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

clearInterval 不會在 React.useEffect 掛鉤中被調用

clearInterval 不會在 React.useEffect 掛鉤中被調用

至尊寶的傳說 2023-01-06 15:58:06
我的 React 游戲有一個<Clock/>組件來跟蹤時間。當游戲暫停時,計時器應該停止。我正在使用 Redux 來管理播放/暫停狀態以及經過的時間。const initialState = { inProgress: false, timeElapsed: 0 }inProgress狀態由另一個組件上的按鈕處理,該按鈕分派一個操作來更新商店(僅針對值inProgress)。該組件在其鉤子中<Clock/>遞增。然而并不清楚。timeElapseduseEffectsetIntervalimport React from 'react';import { connect } from 'react-redux';const Clock = ({ dispatch, inProgress, ticksElapsed }) => {    React.useEffect(() => {        const progressTimer = setInterval(function(){            inProgress ? dispatch({ type: "CLOCK_RUN" }) : clearInterval(progressTimer);        }, 1000)    }, [inProgress]);    return (        <></>    )};let mapStateToProps = ( state ) => {    let { inProgress, ticksElapsed } = state.gameState;    return { inProgress, ticksElapsed };}export default connect(    mapStateToProps,    null,)(Clock);在里面setInterval,什么時候inProgress,false我希望clearInterval(progressTimer)時鐘停止。此外,還有另一個問題,即省略[inProgress]in useEffecthook 會導致計時器以荒謬的速度增加,從而導致應用程序崩潰。謝謝你。
查看完整描述

1 回答

?
桃花長相依

TA貢獻1860條經驗 獲得超8個贊

inProgress是傳遞給 setInterval 的函數的陳舊閉包。

可以通過清除cleanup函數中的interval來解決:

const Clock = ({ dispatch, inProgress, ticksElapsed }) => {

  React.useEffect(() => {

    const progressTimer = setInterval(function () {

      inProgress && dispatch({ type: 'CLOCK_RUN' });

    }, 500);

    return () =>

      //inprogress is stale so when it WAS true

      //  it must now be false for the cleanup to

      //  be called

      inProgress && clearInterval(progressTimer);

  }, [dispatch, inProgress]);


  return <h1>{ticksElapsed}</h1>;

};


const App = () => {

  const [inProgress, setInProgress] = React.useState(false);

  const [ticksElapsed, setTicksElapsed] = React.useState(0);

  const dispatch = React.useCallback(

    () => setTicksElapsed((t) => t + 1),

    []

  );

  return (

    <div>

      <button onClick={() => setInProgress((p) => !p)}>

        {inProgress ? 'stop' : 'start'}

      </button>

      <Clock

        inProgress={inProgress}

        dispatch={dispatch}

        ticksElapsed={ticksElapsed}

      />

    </div>

  );

};

ReactDOM.render(<App />, document.getElementById('root'));

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

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

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


查看完整回答
反對 回復 2023-01-06
  • 1 回答
  • 0 關注
  • 155 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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