Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何仅在使用React将某些内容添加到数组时运行useEffect?_Javascript_Reactjs - Fatal编程技术网

Javascript 如何仅在使用React将某些内容添加到数组时运行useEffect?

Javascript 如何仅在使用React将某些内容添加到数组时运行useEffect?,javascript,reactjs,Javascript,Reactjs,我有一个存储在以下状态的警报列表: const [alerts, setAlerts] = useState([]); 我将所有错误和通知推到该列表,然后在警报框中显示。我想要的是在3000ms之后自动弹出一个添加的警报。以下是我要做的: useEffect(() => { setTimeout(() => { setAlerts([...alerts].splice(0, 1)); }, 3000); }, [alerts]); 然而,我得到的是一个无限循环,它

我有一个存储在以下状态的警报列表:

const [alerts, setAlerts] = useState([]);
我将所有错误和通知推到该列表,然后在警报框中显示。我想要的是在
3000ms
之后自动弹出一个添加的警报。以下是我要做的:

useEffect(() => {
  setTimeout(() => {
    setAlerts([...alerts].splice(0, 1));
  }, 3000);
}, [alerts]);

然而,我得到的是一个无限循环,它会被触发,因为即使我从该警报中移除,它也会发生变化。所以我想我只需要在警报数组中添加一些东西时触发上面的代码。有什么想法吗?

这取决于您在何处以及如何更改警报阵列。通常,您会有一些警报源,例如来自ajax或其他方面的响应,您可以使用单独的状态来保留原始对象

// this would hold row alerts
const [rawAlerts, setRawAlerts] = useState([]);

//This would hold alerts that you want to display and you only update them in useEffect
const [alerts, setAlerts] = useState([]);

// Here you would update alerts only when rawAlerts gets updated
useEffect(() => {
  setTimeout(() => {
    setAlerts([...rawAlerts].splice(0, 1));
  }, 3000);
}, [rawAlerts]);

不要使用效果:


const [alerts,setAlerts] = useState([]);

const handleAddAlert = (alert) => {
   setTimeout(() => setAlerts(alerts.filter(a => a !== alert)),3000);
   setAlerts([...alerts,alert]);
}


// instead of calling `setAlerts` in your code down here, call `handleAddAlert` with the alert


在这种情况下,您可能希望更手动地处理此问题。我喜欢使用的这类东西是来自的
useproval
hook

//钩子
函数usePrevious(值){
//ref对象是一个通用容器,其当前属性是可变的。。。
//…并可以保存任何值,类似于类上的实例属性
const ref=useRef();
//将当前值存储在ref中
useffect(()=>{
参考电流=值;
},[value]);//仅在值更改时重新运行
//返回以前的值(发生在更新之前,在上面的useEffect中)
返回参考电流;
}
当你发射效果时,我会检查长度以确保它比之前的长度大,类似这样:

const [alerts, setAlerts] = useState([]);

const previousAlerts = usePrevious(alerts);

useEffect(() => {
  if (alerts.length > previousAlerts.length) {
    setTimeout(() => {
      setAlerts([...alerts].splice(0, 1));
    }, 3000);
  }
}, [alerts]);

我知道这个答案可能不像你想的那么简单,但我已经意识到挂钩有时你必须非常明确地使用它们。
usePrevious
可以解决很多类似的问题。

最后一部分有点错误,因为您再次更新了rawAlerts,但我想到了。谢谢一旦有新数据要显示,您将更新was警报,并且一旦更新,useEffect将使用rawAlers提供的数据更新主警报,这些数据将在某处显示。除非我误解了要求。对不起,我很傻,我现在看到了
setAlert
。你真正想要的行为是什么?下面给出了一个合理的答案,即使用
alerts.length
,但您说这不是您想要的。你到底想达到什么目的?@Adam,我的目标是在某些东西被保存或产生错误时向提醒者显示警报,并在X秒内隐藏此警报。如果一次有多个警报,警报也会堆积起来。那么使用
Alerts.length
而不是
Alerts
作为效果的依赖项有什么错呢?@Adam,因为我在X秒后从警报数组中删除了项目,这会再次触发useffect&&setTimeout,所以我得到一个无限循环。@Adam,可能,但是无论如何,setTimeout应该只在向数组中添加某些内容时触发,使用array.length,它也会在从数组中删除某些内容(使用setTimeout代码)时触发,因此它会把事情搞砸。谢谢,我会尝试一下。