在ReactJS中,为什么componentDidMount在尝试包装jquery对话框时一直为我调用



我遵循这个指南使用DOM库,如jquery UI和reactJS。我最后用下面的代码来测试当我改变对话框的一个道具时会发生什么,在本例中是标题。

var Dialog = React.createClass({
  render: function() {
    return React.DOM.div();
  },
  componentDidMount: function() {
    this.node = this.getDOMNode();
    this.dialog = $(this.node).dialog({
      title: this.props.title
    }).data('ui-dialog');
    this.renderDialogContent(this.props);
  },
  componentWillReceiveProps: function(newProps) {
    this.renderDialogContent(newProps);
  },
  renderDialogContent: function(props) {
    React.render(React.DOM.div({}, props.children), this.node);
    if (props.open)
      this.dialog.open();
    else
      this.dialog.close();
  },
  componentWillUnmount: function() {
    this.dialog.destroy();
  },
});
var MyApp = React.createClass({
  render: function() {
    return <Dialog title={"Dialog - " + (new Date().getTime()) - this.props.start} open={true}>
        <h2>This is my dialog content!!!</h2>
    </Dialog>
  }
});
$(document).ready(function()
{
    var start = new Date().getTime();
    setInterval(function() {
      React.render(
      <MyApp startTime={start}/>,
        document.getElementById('container')
      );
    }, 1000);
});

对话框弹出,但每次间隔滴答,另一个对话框被创建。对话框的componentDidMount函数每秒被调用一次。我做错什么了吗?

一般来说,你不应该在组件内部调用React.render。每次间隔滴答,你正在卸载和重新安装对话框,触发componentDidMount。每次发生这种情况,它都会初始化并打开对话框,导致您看到的行为。

我将startTime道具移动到MyApp状态,然后在MyAppcomponentDidMount事件中设置间隔函数。interval函数应该调用setState而不是React.render。这将导致新的时间流向Dialog组件,该组件可以使用componentWillReceiveProps事件来更新对话框的title选项,而无需重新初始化jQuery。

我还建议删除Dialog组件上的open道具,并让React处理卸载过程。您可以根据状态决定是否在MyApp中呈现Dialog组件。

像这样:

var Dialog = React.createClass({
  render: function() {
    return <div>
      {this.props.children}
    </div>;
  },
  componentDidMount: function() {
    var dialog = $(this.getDOMNode()).dialog({
      title: this.props.title
    }).data('ui-dialog');
  },
  componentWillReceiveProps: function (newProps) {
    $(this.getDOMNode()).dialog('option', 'title', newProps.title);
  },
  componentWillUnmount: function() {
    $(this.getDOMNode()).dialog('destroy');
  }
});

var dialogInterval;
var MyApp = React.createClass({
  getInitialState: function() {
    return {
      openDialog: false,
      time: new Date().getTime()
    };
  },
  handleDialogToggleClick: function () {
    this.setState({openDialog: !this.state.openDialog});
  },
  render: function() {
    var dialog;
    if (this.state.openDialog) {
      dialog = <Dialog title={"Dialog - " + this.state.time}>
        <h2>This is my dialog content!!!</h2>
      </Dialog>;
    }
    return <div>
      <button onClick={this.handleDialogToggleClick}>
        Toggle the dialog
      </button>
      {dialog}
    </div>;
  },
  componentDidMount: function () {
    dialogInterval = setInterval(function() {
      this.setState({time: new Date().getTime()});
    }, 1000);
  },
  componentWillUnmount: function () {
    dialogInterval = null;
  }
});
$(document).ready(function() {
  React.render(
    <MyApp />,
    document.getElementById('container')
  );
});

我还没有测试过,但它应该给你一个我在说什么的想法。

最新更新