【问题标题】:Manipulating DOM in componentDidMount() without setTimeout在没有 setTimeout 的情况下在 componentDidMount() 中操作 DOM
【发布时间】:2019-05-01 15:57:41
【问题描述】:

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

当我在 componentDidMount() 中 console.log 渲染元素的 scrollHeight 时,它给了我一个不同的数字,就像我等待 100 毫秒时一样。

我想要实现的是向下滚动到此处描述的元素的末尾How to scroll to bottom in react?

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

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

我还尝试在 componentDidUpdate() 方法中更改 DOM,结果相同。

我在modal-window组件中写了这段代码:

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 来检查 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) 的描述进行操作。

【问题讨论】:

  • componentDidMount() 的全部意义在于确保 DOM 已加载,因此您绝对不想使用 setTimeout。看起来您正在使用父母 componentDidMount() 而不是 Modals?此外,您不应该直接使用 ref 访问 DOM

标签: javascript css reactjs


【解决方案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} />
}

【讨论】:

  • 我现在尝试使用ref,但结果相同。我想我的问题是我使用模态窗口的方式:&lt;Modal&gt; &lt;InboxThread /&gt; &lt;/Modal&gt; 我试图滚动到模态子 InboxThread 组件的底部。当它被内容渲染时,我会填充模态。
  • 投反对票,因为即使ref 被定义为建议它scrollHeightcomponentDidMount 中最初为0。只有setTimeOut 才会返回实际值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-12
  • 1970-01-01
  • 1970-01-01
  • 2022-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多