开发者问题收集

为什么这会导致无限循环?我不明白

2016-12-10
906

目前,代码可以完成我想要的操作,但它也会导致我的应用程序崩溃。我认为这是因为无限循环,但我不确定。 我希望代码检查两个变量,如果一个变量等于另一个变量,我想更改模式的状态。

newTimestamp 根据 ReactPlayer 中传递的秒数每秒更新一次。

在这种情况下,我该如何防止无限循环?

这是我的代码:

import React, { Component } from 'react';
import { Modal, Button, Tooltip, Link, ControlLabel } from 'react-bootstrap';


export class CommentsModalAdmin extends Component {
   constructor(props) {
    super(props);
    this.state = {
      showModal: false,
    };

    this.close = this.close.bind(this);
    this.open = this.open.bind(this);
  }

  componentWillReceiveProps(props){
    const newTimestamp = this.props.newTimestamp;
    const timestamp = this.props.comment.timestamp;
    if (newTimestamp === timestamp ){
      this.setState({ showModal: true });
      this.props.stopVideo();
    }
  }


  close() {
    this.setState({ showModal: false });
    this.props.playVideo();
  }

  open() {
    this.setState({ showModal: true });
    this.props.stopVideo();


  }

  render() {
    const { newTimestamp, city, person, location, title, content, fileLink, timestamp } = this.props.comment;



    return (
      <div className="flex">
        <a onClick={this.open}><span className="modal-bg"><span style={{ height: rand }} className="modal-color" ></span></span></a>

        <Modal show={this.state.showModal} onHide={this.close} bsSize="lg">
          <Modal.Header closeButton>
            <Modal.Title >{title}</Modal.Title>
          </Modal.Header>
          <Modal.Body>
            <p><ControlLabel>Tagged city: </ControlLabel> {city}</p>
          <p><ControlLabel>Tagged person: </ControlLabel> {person}</p>
          <p><ControlLabel>Tagged location: </ControlLabel> {location}</p>
          <p><ControlLabel>Tagged image: </ControlLabel></p>
          <img src={fileLink} width="100%"/>
          <ControlLabel>Tagged content: </ControlLabel> <div dangerouslySetInnerHTML={{__html: content}} />


          </Modal.Body>
          <Modal.Footer>
            <Button onClick={this.close}>Close</Button>
          </Modal.Footer>
        </Modal>
      </div>
    );
  }
}

这些是我看到的错误消息: “未捕获的 RangeError:超出最大调用堆栈大小”

并且

“警告:performUpdateIfNecessary:意外的批处理号(当前 3200,待处理 1783”

我发现添加 this.props.stopVideo(); 导致了循环,但我不明白为什么。有人能解释一下吗?

2个回答

您正在使用 componentWillReceiveProps 方法。每次组件收到新的(或任何)道具时,都会执行此方法。在该方法中,您会触发一个在组件父级中调用的函数,该函数反过来会触发另一个利用 setState 的函数。

componentWillReceiveProps(props) {
  // ...
  this.props.stopVideo();
}

setState 会导致重新渲染,因此也会重新渲染 CommentsModalAdmin 并调用 componentWillReceiveProps 。这会导致循环。

您可能需要修改该方法(或使用类似 props == this.props 的方法来检查道具是否实际发生了变化)。

Fabian Schultz
2016-12-10

我设法通过添加额外的 if/else 条件来解决这个问题,如下所示:

componentWillReceiveProps(nextProps){
    const newTimestamp = this.props.newTimestamp;
    const timestamp = this.props.comment.timestamp;
    if(nextProps !== this.props){
      if(this.state.showModal === false){
        if (newTimestamp === timestamp ){
          this.setState({ showModal: true });
          this.props.stopVideo();
        } 
      }
    }
  }

希望它可以帮助任何遇到类似问题的人。

Deelux
2016-12-10