我有一个Notification组件,该组件应在几秒钟后关闭并调用onClose
属性:
function Notification(props) {
console.log("Notification function component called");
setTimeout(() => {
props.onClose();
}, 4000);
return (
<div>
{props.children}
<button onClick={props.onClose}>Close</button>
</div>
);
}
在我的App中,我有一个保存通知对象的状态,并通过它们进行映射。
class App extends React.Component {
constructor() {
super();
this.pushNotification = this.pushNotification.bind(this);
}
state = {
notifications: {}
};
pushNotification() {
const id = uuid();
const newNotifications = { ...this.state.notifications };
const date = new Date();
newNotifications[id] = {
id,
date: JSON.stringify(date)
};
this.setState({
notifications: newNotifications
});
}
removeNotification(id) {
console.log("removeNotification");
const newNotifications = { ...this.state.notifications };
delete newNotifications[id];
this.setState({
notifications: newNotifications
});
}
render() {
return (
<div className="App">
<button onClick={this.pushNotification}>Push notification</button>
{Object.keys(this.state.notifications).map(
(notificationIndexKey, index) => {
return (
<Notification
originalKey={JSON.stringify(index)}
key={notificationIndexKey}
onClose={() => {
console.log("Notfication fired on close");
this.removeNotification(notificationIndexKey);
}}
>
Notification{" "}
{this.state.notifications[notificationIndexKey].date}
</Notification>
);
}
)}
</div>
);
}
}
我注意到,如果我在状态中推送多个通知,则setTimout会被初始化多次(这很有意义,因为每次状态更新时都会调用render)
我的问题是,您将如何建议对此进行优化,以使超时仅被调用一次。
我尝试过的一种方法是使用删除的项目创建一个数组,并在调用prop之前进行检查。
答案 0 :(得分:2)
在安装组件后,应应用该副作用。 目前,您的代码将在渲染上执行此操作。 渲染函数可以被多次调用。
此代码应反映正确的更改。
class Notification extends React.Component {
componentDidMount() {
setTimeout(this.props.onClose, 4000);
}
render() {
return (
<div>
{props.children}
<button onClick={props.onClose}>Close</button>
</div>
);
}
}
答案 1 :(得分:1)
您可以通过将类属性设置为notificationTimer
初始设置为null来完成此操作,并可以将Notification函数修改为:
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>
);
}
在关闭函数中,您可以执行以下操作:
onClose() {
// Your code.
if (this.notificationTimer) {
clearTimeout(this.notificationTimer);
this.notificationTimer = null;
}
}
这不会让您创建多个计时器。