【问题标题】:React native setInterval useState反应原生 setInterval useState
【发布时间】:2021-08-20 12:58:03
【问题描述】:

我正在创建间隔计数器,下面的代码工作正常。但是我对这段代码有几个我不明白的问题。

import React, { useState, useEffect } from 'react';
import {View, Text} from 'react-native'

const Interval = () => {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      console.log(`seconds: ${seconds}`)
      setSeconds(seconds => seconds + 1);
    }, 1000);
    return () => clearInterval(interval);
  }, []);

  return (
      <View>
        <Text>
          {seconds} seconds have elapsed since mounting.
        </Text>
      </View>
  );
};

export default IntervalExample;
  1. 如果我更简单地使用 setSeconds(seconds =&gt; seconds + 1); 而不是 setSeconds(seconds + 1);,为什么这不起作用?
  2. 为什么console.log(`seconds: ${seconds}`) 总是以0 登录?

【问题讨论】:

  • 我检查了一下,你的代码有效。您的代码中唯一的问题是您没有正确关闭 Text 标签。
  • @TayyabMazhar 抱歉,感谢提及,我编辑了我的帖子。是的,它工作正常。但是我想知道关于我在帖子中提到的代码的两件事。

标签: reactjs react-native react-hooks setinterval use-state


【解决方案1】:

使用这个;

useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(seconds + 1);
      console.log(seconds)
    }, 1000);

    return () => clearInterval(interval);
  }, [seconds]);

【讨论】:

  • 好的。所以这样做的原因是没有提到不断变化的变量,即seconds
  • [seconds] 在使用setSeconds(seconds =&gt; seconds + 1)时是不必要的
  • 无需每次秒值变化时运行效果。这也会导致之前的间隔被清除,并且每个间隔都创建一个新的间隔,这是完全没用的。
  • @TayyabMazhar 如果这不在 useEffect 块内,则不会卸载间隔,进程将永远运行,甚至移动到另一个屏幕。
  • @JohnStuart 你可以。只需在从 setSeconds 返回之前将新值存储在局部变量中,然后将该变量传递给您想要的任何函数。
【解决方案2】:

要运行useEffect,您需要将变量作为第二个参数传递(在您的情况下,它是seconds)。当此变量发生变化时,useEffect 将再次运行。

来自文档:

如果传递一个空数组([]),则效果内的道具和状态将始终具有其初始值。虽然将 [] 作为第二个参数传递更接近于熟悉的 componentDidMount 和 componentWillUnmount 心理模型,但通常有更好的解决方案来避免过于频繁地重新运行效果。另外,不要忘记 React 会延迟运行 useEffect 直到浏览器绘制完成,所以做额外的工作不是问题。

也就是说,您需要将第二个变量传递给 useEfect:

useEffect(() => {...}, [seconds])

在这种情况下,您可以使用setSeconds(seconds + 1); 而不是传递函数。

完整代码:

useEffect(() => {
 const interval = setInterval(() => {
   console.log(`seconds: ${seconds}`)
   setSeconds(seconds + 1)
  }, 1000)
 return () => clearInterval(interval)
}, [seconds])

【讨论】:

  • 谢谢。很好的解释。
猜你喜欢
  • 2021-01-30
  • 2021-08-05
  • 1970-01-01
  • 2020-12-21
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 2021-08-01
  • 1970-01-01
相关资源
最近更新 更多