javascript - 在没有 setTimeout 的情况下在 componentDidMount() 中操作 DOM

标签 javascript css reactjs

我想在 componentDidMount() 方法中操作 ReactJS 中的 DOM。我的问题是此时 DOM 没有以某种方式完全呈现,我需要一个 setTimeout 函数,我宁愿忽略它。

当我在 componentDidMount() 中对渲染元素的 scrollHeight 进行 console.log 时,它会给我一个不同的数字,因为当我等待比方说 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 之类的东西。

更新

我有一个模态窗口组件,它为我的收件箱线程呈现一个像这样的 child :

<Modal>
  <InboxThread />
</Modal>

问题是,我需要等到模态窗口组件在 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) .

最佳答案

如果您使用 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} />
}

关于javascript - 在没有 setTimeout 的情况下在 componentDidMount() 中操作 DOM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55939058/

相关文章:

javascript - 如何处理绑定(bind)到同一 ng-model 的不同输入类型?

javascript - 使用 JavaScript JQUERY 或 CSS 制作可扩展的顶部栏

javascript - React Native 进度 View iOS 不重新渲染

javascript - 从 React.JS 状态调用方法

javascript - 状态不更新

javascript - aws DynamoDB getItem InvalidParameterType 错误

javascript - 是否可以使用 javascript 从浏览器中获取 "read"mercurial repos?

Javascript - 如何用 promise 返回对象

javascript - 从图像中裁剪一个三 Angular 形并将其放在原始图像 CSS 下方

javascript - jQuery .toggle 堆叠样式