Javascript React函数组件setTimeout-多次渲染调用和重新渲染(推荐方法)(多次激发)

Javascript React函数组件setTimeout-多次渲染调用和重新渲染(推荐方法)(多次激发),javascript,reactjs,Javascript,Reactjs,我有一个通知组件,它应该在几秒钟后自动关闭,并调用onCloseprop: 功能通知(道具){ log(“调用通知函数组件”); 设置超时(()=>{ props.onClose(); }, 4000); 返回( {props.children} 接近 ); } 在我的应用程序中,我有一个保存通知对象的状态,并通过它们进行映射 类应用程序扩展了React.Component{ 构造函数(){ 超级(); this.pushNotification=this.pushNotification.b

我有一个通知组件,它应该在几秒钟后自动关闭,并调用
onClose
prop:

功能通知(道具){
log(“调用通知函数组件”);
设置超时(()=>{
props.onClose();
}, 4000);
返回(
{props.children}
接近
);
}
在我的应用程序中,我有一个保存通知对象的状态,并通过它们进行映射

类应用程序扩展了React.Component{
构造函数(){
超级();
this.pushNotification=this.pushNotification.bind(this);
}
状态={
通知:{}
};
pushNotification(){
常量id=uuid();
const newNotifications={…this.state.notifications};
const date=新日期();
新通知[id]={
身份证件
日期:JSON.stringify(日期)
};
这是我的国家({
通知:新通知
});
}
重新通知(id){
控制台日志(“重新通知”);
const newNotifications={…this.state.notifications};
删除新通知[id];
这是我的国家({
通知:新通知
});
}
render(){
返回(
推送通知
{Object.keys(this.state.notifications).map(
(notificationIndexKey,索引)=>{
返回(
{
console.log(“关闭时触发通知”);
这是。removeNotification(notificationIndexKey);
}}
>
通知{“}
{this.state.notificationIndexKey].date}
);
}
)}
);
}
}
我注意到,如果在我的状态中推送多个通知,setTimout会被初始化多次(这是有意义的,因为每次更新状态时都会调用render)

我的问题是,您建议如何对此进行优化,以便只调用一次超时

我尝试过的一种方法是创建一个数组,其中包含我在调用道具之前移除并检查的项目


沙箱:

您可以通过保持类属性(例如
notificationTimer
最初设置为null)来完成此操作,并可以将通知函数修改为:

function Notification(props) {
  console.log("Notification function component called");

  if (!this.notificationTimer)
    this.notificationTimer = setTimeout(() => {
      props.onClose();
    }, 4000);
  }

  return (
    <div>
      {props.children}
      <button onClick={props.onClose}>Close</button>
    </div>
  );
}

这将不允许您创建多个计时器。

您应该在安装组件后应用该副作用。 当前,您的代码将在渲染时执行此操作。 可以多次调用渲染函数

此代码应反映正确的更改

类通知扩展了React.Component{
componentDidMount(){
setTimeout(this.props.onClose,4000);
}
render(){
返回(
{props.children}
接近
);
}
}

听起来是个很好的主意,除了通知功能是一个react组件,它没有与应用程序代码相关的
。我也希望能够在应用程序之外使用该组件。好吧,在Angular中,我们通过单独的通知服务来实现这一点,该服务保存对计时器的引用。谢谢@Pratyush,听起来不错,将尝试一些其他想法,并会让你知道尼斯!这很有效。我不想将函数组件转换为类,但我认为这看起来更简洁。谢谢你/穆尔图米埃斯科德林!或者你可以做一个简单的反应钩。这将不要求通知组件成为类
useffect(()=>{const timer=setTimeout(props.onClose,4000)return()=>cleartimout(timer)},[])
The
[]
意味着它将执行一次,它返回的函数将在组件卸载时执行。
onClose() {
  // Your code.

  if (this.notificationTimer) {
    clearTimeout(this.notificationTimer);
    this.notificationTimer = null;
  }
}