javascript - React,两个组件运行两次超时卸载;相同的卸载被调用两次

标签 javascript reactjs

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/

相关文章:

javascript - 尝试使用 React 检索 API 数据时出现问题

javascript - react 路由器索引路由始终处于事件状态

javascript - 将鼠标悬停在下拉值上

javascript - 每 30 秒重置一次计数器

javascript - redux - 当一个资源依赖于另一个资源时,如何适本地更新它们

javascript - 如何延迟 NavLink 的 react ?

javascript - 在 REACT 中将数据发送到其后代的最佳方法是什么

javascript - 如何使用 javascript 识别剪贴蒙版而不使用 Photoshop 的比例?

javascript - AngularJS 字符串在 HTML 中替换

node.js - 创建 react 应用程序错误找不到模块 './node'