React Components和setInterval ID

时间:2018-05-15 18:12:00

标签: javascript reactjs setinterval

我正在尝试编写一个弹出的Notification React组件,然后在5秒后消失。可以有许多Notifications堆叠在一起,因此我保留了它们的列表并使用map()显示它们。但是,我注意到如果我按顺序添加通知并在每个通知中声明setInterval ID,则在它们卸载时,ID会从一个组件迁移到下一个组件。例如,假设通知ID 111获取setInterval ID 1,然后创建通知ID 222并获取setInterval ID 2.一旦通知111消失,突然通知222的setInterval ID现在为1!以下是相关代码:

class Notification extends Component {

  constructor(props) {
    super(props);
    this.onClose = this.onClose.bind(this);
    this.countdownTimer = null;
    this.secondsLeft = null;
  }

  componentDidMount() {
    if(this.secondsLeft === null) {
      this.secondsLeft = 5;
      this.countdownTimer = setInterval(() => {
        this.secondsLeft = this.secondsLeft - 1;
        if (this.secondsLeft <= 0) {
          this.onClose();
        };
      }, 1000);
    };
  }

  componentWillUnmount() {
    clearInterval(this.countdownTimer);
  }

  onClose() {
    this.props.removeNotification(this.props.notification.id);
  }

// render() and other irrelevant code removed
}

为什么在删除组件后,值this.countdownTimer会被转移到另一个组件?可能是通知列表通过列表中的位置指向它们而不是给出的道具?

编辑:以下是相关日志来证明:

// Notification ID: 5a8 , timer ID: 15 , secondsLeft: 5
// Notification ID: 15a , timer ID: 16 , secondsLeft: 5
// Notification ID: 5a8 , timer ID: 15 , secondsLeft: 4
// Notification ID: 15a , timer ID: 16 , secondsLeft: 4
// Notification ID: 5a8 , timer ID: 15 , secondsLeft: 3
// Notification ID: 15a , timer ID: 16 , secondsLeft: 3
// Notification ID: 5a8 , timer ID: 15 , secondsLeft: 2
// Notification ID: 15a , timer ID: 16 , secondsLeft: 2
// Notification ID: 5a8 , timer ID: 15 , secondsLeft: 1
// Notification ID: 15a , timer ID: 15 , secondsLeft: 0

1 个答案:

答案 0 :(得分:0)

我意识到自己的错误。我在通知组件本身设置了key道具。我应该在初始化组件时在key内设置map()。例如:

class NotificationsList extends Component {
    render() {
      return (
        <div className="NotificationsList">
          { this.props.notifications.map(notification => (
            <Notification
              notification={notification}
              key={notification.id}
            />
          ))}
        </div>
      );
    }
}

最初我反而这样做了(这是错误的):

class Notification extends Component {

  render() {
    return (
      <AnimatedAlert
        key={this.props.notification.id}
      </AnimatedAlert>
    );
  }
}