在不使用setTimeout

时间:2019-05-01 15:57:41

标签: javascript css reactjs

我想在componentDidMount()方法中操作ReactJS中的DOM。我的问题是,这时DOM尚未完全呈现,我需要一个setTimeout函数,我宁愿忽略它。

当我console.log在componentDidMount()中记录渲染元素的scrollHeight时,它给我的数字与等待100毫秒时的数字不同。

我要实现的是向下滚动到此处How to scroll to bottom in react?

中描述的元素的末尾

该组件是一个模态窗口,它呈现另一个组件的{this.props.children}。模态窗口使用visibility: hiddenopacity: 0渲染到DOM中,并且具有窗口的高度(当它首次出现在页面上时)。通过单击按钮,它会显示出来,并且仍然具有窗口的高度,直到我等待几毫秒。

我想,当需要setTimeout时,我在这里做错了,但是我没有发现什么。

我还试图用相同的结果更改componentDidUpdate()方法中的DOM。

我在模态窗口组件中编写了这段代码:

componentDidMount() {
  console.log(document.querySelector('.myModal').scrollHeight);
  setTimeout(function() {
    console.log(document.querySelector('.myModal').scrollHeight);
  }, 100);
}

第一个console.log例如497,第二个类似952。

更新

我有一个模态窗口组件,例如,它为我的收件箱线程渲染了一个孩子:

<Modal>
  <InboxThread />
</Modal>

问题是,我需要等到modal-window组件在Modal.js中像这样呈现其子级:

render() {
    return (
      <React.Fragment>
        {this.props.children}
      </React.Fragment>
    );
  }

所以最后我的解决方案是从父组件中传递props中的一个方法,在其中我调用模态来检查Modal.js中的componentDidUpdate()。

我的代码现在在父组件中如下所示:

...
export default class InboxThreadList extends React.Component {
  constructor(props) {
    super(props);
    this.scrollToModalBottom = this.scrollToModalBottom.bind(this);
  }
  render() {
    return (
    <React.Fragment>
      ...
      <Modal onRender={this.scrollToModalBottom}>
        <InboxThread/>
      </Modal>
    </React.Fragment>
    )
  }
  scrollToModalBottom() {
    const myModalObject = document.querySelector('.myModal');
    myModalObject.scrollTop = myModalObject.scrollHeight;
  }
}

在Modal.js中:

...
export default class Modal extends React.Component {
  ...
  componentDidUpdate() {
    if ('onRender' in this.props) {
      this.props.onRender();
    }
  }
  render() {
    return (
      <div className={'myModal'}>
        {this.props.children}
      </div>
    );
  }

我知道!我仍然应该使用refs而不是document.querySelector,我将按照React - Passing ref from dumb component(child) to smart component(parent)的说明进行操作。

1 个答案:

答案 0 :(得分:1)

如果您使用ref(只要该元素始终在render()中呈现),则可以保证在componentDidMount运行之前将其解析:

componentDidMount() {
  // can use any refs here
}

componentDidUpdate() {
  // can use any refs here
}

render() {
  // as long as those refs were rendered!
  return <div ref={/* ... */} />;
}

componentDidMount called BEFORE ref callback

因此,在您的情况下,您可能会像这样进行编码:

componentDidMount() {
  console.log(this.mymodal.scrollHeight)
}

render() {
 return <div className="mymodal" ref={ref => this.mymodal = ref} />
}