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函数与父组件中的此函数挂钩,该父组件正在管理Notification组件的数据“模型”数组:
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函数继续调用“ dismount”组件(5000ms,仍在DOM中) )导致错误:
Warning: Can't call setState (or forceUpdate) on an unmounted component.
但是真正令我困惑的是,如果我检查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>
})
}
答案 0 :(得分:0)
这是通知组件中的逻辑错误:
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>
)
}
}