Javascript 对animationend问题作出反应
我在React中创建了一个简单的通知服务,遇到了一个非常奇怪的问题,我找不到任何提及或解决方案 我的组件有一个通知消息数组。每个“通知”都有一个“onClick”和“onAnimationEnd”绑定,该绑定调用一个函数,该函数将从通知数组中删除它们。其基本思想是通知将逐渐消失(使用CSS动画),然后被删除,或者允许用户手动单击通知以删除它 有趣的bug如下所示。如果添加两个通知,第一个通知将触发其onAnimationEnd并删除自身。剩下的通知将突然跳转到css动画的末尾,并且永远不会触发自己的onAnimationEnd 更奇怪的是,如果您添加四个通知,其中正好有两个会出现上述错误,而另外两个功能正常 还值得一提的是,如果您创建了两个通知,并单击其中一个,然后手动将其删除,其余的通知将正常运行并触发其自己的onAnimationEnd功能 因此,我不得不得出结论,通过数组的循环和onAnimationEnd触发器的某些组合在react中受到了某种程度的窃听,除非有人能指出这个问题的解决方案 反应代码Javascript 对animationend问题作出反应,javascript,css,reactjs,Javascript,Css,Reactjs,我在React中创建了一个简单的通知服务,遇到了一个非常奇怪的问题,我找不到任何提及或解决方案 我的组件有一个通知消息数组。每个“通知”都有一个“onClick”和“onAnimationEnd”绑定,该绑定调用一个函数,该函数将从通知数组中删除它们。其基本思想是通知将逐渐消失(使用CSS动画),然后被删除,或者允许用户手动单击通知以删除它 有趣的bug如下所示。如果添加两个通知,第一个通知将触发其onAnimationEnd并删除自身。剩下的通知将突然跳转到css动画的末尾,并且永远不会触发自
class Test extends React.Component {
constructor (props) {
super(props)
this.state = {
notifications: []
}
}
add = () => {
this.setState({notifications: [...this.state.notifications, 'Test']})
}
remove = (notification) => {
let notificationArray = this.state.notifications
notificationArray.splice(notificationArray.indexOf(notification), 1)
this.setState({notifications: notificationArray})
}
render() {
return (
<div>
<button onClick={this.add}>Add Notification</button>
<div className="notification-container">
{this.state.notifications.map(
(notification,i) => {
return (
<div onAnimationEnd={()=>this.remove(notification)}
onClick={() => this.remove(notification)}
className="notification"
key={i}>
{notification}
</div>
)
}
)}
</div>
</div>
);
}
}
ReactDOM.render(
<Test />,
document.getElementById('root')
);
工作代码笔链接
您正在使用数组索引作为组件键:
{this.state.notifications.map(
(notification,i) => {
return (
<div onAnimationEnd={()=>this.remove(notification)}
onClick={() => this.remove(notification)}
className="notification"
key={i}>
{notification}
</div>
)
}
)}
数组索引只能在万不得已的情况下用作组件键。Dylan感谢您的回复。但是,如果是这种情况,为什么删除通知元素的onClick版本可以正常工作?他们基本上在做完全相同的事情。onClick将删除元素,并导致重新计算索引键,但动画在这种情况下继续运行很难100%确定,因为我无法100%确定React如何使用键进行优化,但可以想象这样的情况:(生成通知0)->(生成通知1)->(提前解除通知0)->(通知1继承了0的
onAnimationEnd
,因为React认为它实际上是0)。现在想象一下这种情况,而不手动取消:(0的onAnimationEnd
激发)->(1继承了0的onAnimationEnd
,但动画已经结束,因此它永远不会激发)。如果您的通知在文本中更复杂,我保证只使用onClick()就会发生奇怪的事情
,它们现在并不明显,因为您的所有通知都只是“测试”。不过,您不必相信我的话,试试看!@mls3590712在这里,我想到了一个演示的方法。在您的代码笔中,生成1个通知,等待~4秒,然后生成第二个通知。生成第二个通知后立即生成第二个通知n、 取消第一个通知(位于顶部的通知)。剩余的通知将立即在淡入淡出的过程中进行一部分并提前消失。我可以确认您的唯一密钥解决方案确实解决了问题。发生这种奇怪的行为(正好有一半不起作用,但另一半起作用)让我很恼火。感谢您的洞察力。
{this.state.notifications.map(
(notification,i) => {
return (
<div onAnimationEnd={()=>this.remove(notification)}
onClick={() => this.remove(notification)}
className="notification"
key={i}>
{notification}
</div>
)
}
)}
add = () => {
this.setState({notifications: [...this.state.notifications, Math.random().toString()]})
}
...
key={notification}