首页 > 解决方案 > Javascript setInterval 未检测到全局变量更改(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变量设置为假。我不明白为什么,因为其他功能和组件isConnected考虑得当。

知道为什么其他函数和组件会注册 的更改isConnected,但readStatus称为计时器的函数不会?

标签: javascriptreactjstimerscopeclosures

解决方案


看来这是一个 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从第一次渲染开始始终具有对最新值的引用

推荐阅读