TL;DR:这正在发生:https://jsfiddle.net/69z2wepo/204124/ 为什么他们会同时消失?应仅应用于一个组件的样式似乎同时应用于两者。
此版本:https://jsfiddle.net/69z2wepo/204131/将它们变成红色而不是不透明度改变的地方使问题更加清楚;红色样式应用于两个通知,即使超时只为一个通知设置。
当 Notification 组件挂载时,它会为可变延迟设置超时:
componentDidMount = () => {
let timeout = parseInt(this.props.decay) || 2000
this.setState({
dismissTimeout: setTimeout(() => {
this.fadeOutFunction();
setTimeout(() => {
this.dismiss();
}, 125)
}, timeout)
})
}
}
淡出动画将在 100 毫秒内发生,然后组件将被卸载:
fadeOutFunction = () => {
let opacity = Math.floor(this.state.style.opacity * 10)
if ( opacity > 0) {
opacity -= 1;
setTimeout(() => { this.fadeOutFunction() }, 10)
}
let newState = Object.assign({}, this.state.style)
newState.opacity = opacity / 10
this.setState({ style: newState })
}
dismiss 函数连接到父组件中的这个函数,父组件管理通知组件的数据“模型”数组:
dismiss = () => {
this.props.dismiss(this.props.code);
}
// in parent
dismissNotification = (code) => {
this.setState({ notifications: this.state.notifications.filter (
n => n.code != code
)})
}
设置了两个通知,一个有 2000 衰减,一个有 5000 衰减。
当第一个组件完成淡出时,会发生一些非常奇怪的行为;两个组件都失去了它们的不透明度(设置为 0),并且为错误的组件调用了 dismount 函数......疯狂的是 fadeOut 函数继续调用'dismounted'组件(5000ms 一个,仍然在 DOM 中) 导致错误:
警告:无法在未安装的组件上调用 setState(或 forceUpdate)。
但真正令我困惑的是,如果我检查 dismissNotification
,它会过滤掉正确的通知。
更新:jsFiddle 现在重现错误: https://jsfiddle.net/69z2wepo/204124/
但是没有任何问题!查看我的代码,我认为没有任何显着差异,事实上,当我将 fadeOut 函数更改为“将组件设置为红色”时:
makeRedFunction = () => {
this.setState({ style: {backgroundColor: "red"} })
}
组件会在正确的时间改变它们的样式,并在没有错误的情况下正确地关闭。
很抱歉,这有点含糊:/我真的希望我知道如何获得更多正确的信息,但是.. 为什么设置不透明度不会在 codefiddle 上触发错误,而是在我的应用程序中触发错误?为什么不透明度会导致这种奇怪的跨组件行为,而颜色却不会?
我是否遗漏了一些对项目中的动画至关重要的依赖项?我已经看到有动画库,但对于这些简单的东西,我宁愿自己编写代码。
**编辑:** 我的父组件的渲染
{
this.state.notifications.map( (n, idx) => {
return <Notification
key={idx}
code={n.code}
decay={n.decay}
dismiss={ () =>{this.dismissNotification(n.code)}}
>
{ n.message }
</Notification>
})
}
最佳答案
这是 Notification 组件中的一个逻辑错误:
setTimeout(() => {
this.fadeOutFunction();
setTimeout(() => { // <--- This part is uneccessary
this.dismiss();
}, 125)
}, timeout)
将其更改为:
class Notification extends React.Component {
constructor(props) {
super(props)
this.state = {
style: { opacity: 1 }
}
}
componentDidMount = () => {
let timeout = parseInt(this.props.decay) || 2000
setTimeout(() => {
this.fadeOutFunction();
}, timeout)
}
fadeOutFunction = () => {
let opacity = Math.floor(this.state.style.opacity * 10)
if (opacity > 0) {
opacity -= 1
setTimeout( () => { this.fadeOutFunction() }, 10)
}
let newState = Object.assign({}, this.state.style)
newState.opacity = opacity / 10
this.setState({ style: newState })
}
dismiss = () => {
this.props.dismiss(this.props.code)
}
render () {
return(
<div style={this.state.style}>{this.props.children}</div>
)
}
}
关于javascript - React,两个组件运行两次超时卸载;相同的卸载被调用两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51034112/