簡體   English   中英

Javascript setInterval 未檢測到全局變量更改(React Native)

[英]Javascript setInterval not detecting global variable change (React Native)

我正在開發用於與 BLE 設備通信的 React Native 應用程序。 為了跟蹤連接是否仍然建立,我在我的組件中使用了一個狀態。

  const [isConnected, setIsConnected] = useState(props.route.params.isConnected || false);

在我的useEffect鈎子中,我開始一個間隔來重復讀取我的 BLE 設備的狀態,如下所示:

  useEffect(() => {
    AppState.addEventListener('change', onAppStateChange);
    updateStatusRepeatedly.current = setInterval(readStatus, 5000);
    return () => {
      AppState.removeEventListener('change', onAppStateChange);
      clearInterval(updateStatusRepeatedly.current);
    };
  }, []);

readStatus函數每 5 秒調用一次,它按預期工作。 但不應執行 的內容。 所以我把它包裝在一個基於isConnected變量的條件語句中。

const readStatus = () => {
  if (isConnected) {
    readAddedCharge();
    readPowerMeasurement();
  } 
};

每次都執行內容。 即使isConnected變量設置為 false。 我不明白為什么,因為其他功能和組件正確地考慮了isConnected

知道為什么其他函數和組件會注冊isConnected的更改,但作為計時器調用的readStatus isConnected不會嗎?

看起來這是一個 React 的函數組件。 讓我們做一個最小的例子:

function MyComp() {
  const [foo, setFoo] = useState(0);
  useEffect(() => {
    setInterval(() => {
      console.log(foo); // this will always show 0
      setFoo(foo + 1);
    }, 5000);
  }, []);
}

這是因為在函數的作用域中, foo是一個永遠不會改變的const 隨着新值再次“改變”運行函數foo手段foo ,這是因為你不使用,無論如何useEffect(..., [])被稱為只在第一次呈現。

可能的解決方案:

  1. 清除並重新創建每個組件渲染的間隔
  2. 使用useRef存儲該值,以便第一次渲染的readStatus始終具有對最新值的引用

我遇到了同樣的問題,但找到了解決方案。 我們創建了一個執行間隔的組件,它在事物的反應端調用一個外部函數。 例如,請參閱下面的代碼。

   const intervalExample = () => {
     const [timeslots, setTimeslots] = useState([]);
     
     const loopingFunction = () => {
        if (timeslots.length > 0) {
            timeslots.map((val) => {
                if (val['purchasing'] == true) {                    
                    doStuff();
                }
            });
        }
    }

    const doStuff = () = >{
    }


     return <div><IntervalRunner onInterval={loopingFunction} milliseconds="5000" /></div>

}


const IntervalRunner = (props) => {
    const [increments, setIncrements] = useState(0);
    const intervalCall = () => {
        setIncrements(increments+1);
         
    }
    
    useEffect(()=>{
         props.onInterval();
         setTimeout(intervalCall, props.milliseconds)
    }
    , [increments])
     return '';
     
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM