React UseEffect示例不起作用原因

时间:2019-11-13 10:57:56

标签: reactjs react-hooks

为什么这不能像正常的一秒钟计数器一样工作?


function UseEffectBugCounter() {
  const [count, setCount] = React.useState(0);

  React.useEffect(() => {
    const intervalId = setInterval(() => {
      setCount(count + 1);
      console.log(count);
    }, 1000);

    return () => clearInterval(intervalId);
  }, []);

  return <div>The count is: {count}</div>;
}

示例:https://codesandbox.io/s/sparkling-rgb-6ebcp

-是因为过时的关闭吗?

-是因为计数是状态变量,并且在状态更新后将重新渲染组件,所以将创建一个新的间隔来创建某种循环吗?

-还有其他东西吗?

我正在寻找一个为什么可能在此答案中出现的原因,有几篇不同的文章说明了为什么它不起作用(如上所述)。但是到目前为止,没有人能够提供一个很好的论据。

5 个答案:

答案 0 :(得分:2)

您可以将回调用于设置状态以使用最新的计数器值:

setCount(count => (count + 1));

答案 1 :(得分:0)

您可能需要在count中添加对useEffect的依赖性。当前useEffect仅在安装上被调用,此后不被调用(即当计数值更改时)。

因此它总是说0,因为useEffect仅执行一次(在mount上),而此时计数值设置为0。因此,由于关闭,它每次在setInterval上记录为0。

我已经更新了代码沙箱以查找原因和有意义的日志。这是沙盒链接:https://codesandbox.io/s/admiring-thompson-uz2xe

如何查找闭合值:您可以检查日志并遍历原型对象以找到[[Scopes]],并将获得以下屏幕快照中所示的值:enter image description here

这将起作用:

React.useEffect(() => {
    const intervalId = setInterval(() => {
      setCount(count + 1);
      console.log(count);
    }, 1000);

    return () => clearInterval(intervalId);
  }, [count]);

您可以查看以下文档:https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect

您也可以阅读:https://overreacted.io/making-setinterval-declarative-with-react-hooks/

希望这会有所帮助!

答案 2 :(得分:0)

如果您删除了第二个参数供useEffect使用,则您的状态会发生变化,但始终会呈现您的应用程序,但这是一种不好的做法。您需要在第二个参数中选择需要观看的参数...

具有选定参数的示例:

React.useEffect(() => {
    const intervalId = setInterval(() => {
      setCount(count + 1);
      console.log(count);
    }, 1000);

    return () => clearInterval(intervalId);
  }[count]);

React.useEffect(() => {
    const intervalId = setInterval(() => {
      setCount(count + 1);
      console.log(count);
    }, 1000);

    return () => clearInterval(intervalId);
  });

答案 3 :(得分:0)

因为您没有添加count来使用Effect的依赖关系,所以效果数内部始终为0

您应该使用useReducer来解决问题:

function UseEffectBugCounter() {
  const [count, dispatchCount] = React.useReducer((state, { type }) => {
    switch(type) {
      case 'inc':
        return state + 1
      default:
        return state
    }
  }, 0);

  React.useEffect(() => {
    const intervalId = setInterval(() => {
      dispatchCount({ type: 'inc'})
    }, 1000);
    return () => clearInterval(intervalId);
  }, []);
  return <div>The count is: {count}</div>;
}

答案 4 :(得分:0)

您需要传递计数而不是useEffect

中的空白数组
function UseEffectBugCounter() {
  const [count, setCount] = React.useState(0);
  React.useEffect(() => {
    const intervalId = setInterval(() => {
      setCount(count + 1);
      console.log(count);
    }, 1000);
    return () => clearInterval(intervalId);
  },[count]);
  return <div>The count is: {count}</div>;
}