Javascript 为什么我的计时器组件在将依赖项传递给useEffect时行为异常?

Javascript 为什么我的计时器组件在将依赖项传递给useEffect时行为异常?,javascript,reactjs,Javascript,Reactjs,我使用useffect创建了以下计时器,并将函数依赖项传递给它: const Timer = () => { const [count, setCount] = useState(0); const setId = () => { const id = setInterval(() => { setCount(count + 1); }, 1000); return () => clearInterval(id); }

我使用
useffect
创建了以下计时器,并将函数依赖项传递给它:

const Timer = () => {
  const [count, setCount] = useState(0);
  const setId = () => {
    const id = setInterval(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(id);
  }
  useEffect(() => {
    setId();
  }, [setId])
}

然而,计时器的行为异常:前几秒是正常的,然后它开始随机显示计数。是什么导致了这个问题?正确的方法是什么?

卸载时清除间隔

useEffect(() => {
    let id;
    const setId = () => {
      id = setInterval(() => {
        setCount((count) => count + 1);
      }, 1000);
    };
    setId();
    return () => clearInterval(id);
  }, []);


检查这个片段,一个好的文档

import React,{useCallback,useState,useffect,useRef}来自“React”;
导入“/styles.css”;
导出默认函数App(){
let[count,setCount]=useState(0);
useInterval(()=>{
设置计数(计数+1);
}, 1000);
返回{count};
}
函数useInterval(回调、延迟){
const savedCallback=useRef();
//记住最近的回拨。
useffect(()=>{
savedCallback.current=回调;
},[callback]);
//设置间歇时间。
useffect(()=>{
函数tick(){
savedCallback.current();
}
如果(延迟!==null){
让id=设置间隔(滴答声,延迟);
return()=>clearInterval(id);
}
},[延迟];
}
工作

更新

正如keith所建议的,不要将函数传递给array deps,如下所示

import React, { useState, useEffect } from "react";
import "./styles.css";

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCount((count) => count + 1);
    }, 1000);

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

  return <div>{count}</div>;
}
import React,{useState,useffect}来自“React”;
导入“/styles.css”;
导出默认函数App(){
const[count,setCount]=useState(0);
useffect(()=>{
常量间隔=设置间隔(()=>{
setCount((count)=>count+1);
}, 1000);
return()=>{
间隔时间;
};
}, []);
返回{count};
}

@DILEEP THOMAS update类似的问题的答案是我会这样做的

但是@thinkvantagedu评论

还是不太确定为什么可以通过

也许需要更多的解释,不幸的是评论太多了,所以我发布了这个

要回答这个问题,我们需要后退一步,首先要问,依赖关系数组的意义是什么?。简单的答案是useEffect中的任何内容,这些内容取决于如果从useState或需要不同处理的道具更改,它将需要放入数组中

例如,如果您有一个只显示用户配置文件的组件,但获取此信息是异步的,那么需要useEffect。它可能看起来像这样->

<UserProfile userId={userId}/>

现在的问题是,如果我们将
[]
作为依赖项传递,useEffect将不会为新的userId重新激发,因此道具可能会说
userId=2
,但我们当前存储在状态中的数据是针对
userId=1
,。。所以对于像这样的东西,
[props.userId]
完全有意义

那么回到OP的组件
这里有什么东西会改变呢?好吧,这不是道具,因为没有传递任何道具。那么关于
count
你可能会问,那么再次问你自己,count的状态是否保证一个setInterval的新实例被销毁/创建了?。当然,这里的答案是否定的,因此在这里传递
[]
完全有意义


希望这是有意义的,.

您的useEffect将持续运行,因为
setId
是对函数的新调用,为什么要将其传递给useEffect?试试看useCallback@Keith因为它是一种副作用?它不想成为你使用效果的一部分,。。这是一个毫无意义的检查,就像我指出的,每次渲染都是一个新函数的新调用;它总是会着火。这里的副作用是组件内部的,通常useEffect检查是针对您传递到的内容props@Keith我想你的意思是“函数的实例化”,而不是“调用”?除非
setId
是一个非常昂贵的操作,否则useCalback在这里是没有意义的。好吧,那更好的方法是什么,通常,当我们将数组deps作为函数传递时,它会进入无限循环,只是不要将函数作为deps传递,甚至不知道OP为什么要这样做。添加了:),谢谢,这里可以将空数组作为依赖项传递吗?
<UserProfile userId={userId}/>