在React.js中的setState之后自动滚动到渲染元素

时间:2018-03-13 10:39:15

标签: reactjs

假设我在页面顶部的列表项上有一些setState声明,如下所示:

<DropdownMenu >
    <DropdownItem className="channel-setting__btn"
      onClick={() => this.setState({ facebookFields: true, youtubeFields: true })}>All</DropdownItem>

    <DropdownItem
      className="channel-setting__btn"
      onClick={() => this.setState({ facebookFields: true, youtubeFields: false })}>Facebook
    </DropdownItem>

    <DropdownItem
      className="channel-setting__btn"
      onClick={() => this.setState({ facebookFields: false, youtubeFields: true })}>Youtube
    </DropdownItem>

</DropdownMenu>

有没有什么方法,当我点击DropDownItem然后无论DOM元素呈现什么,页面自动滚动到该部分或元素已在页面上呈现的位置,在此cas中元素是Facebook和youtube的不同形式它将在最后呈现,并且非常接近页面末尾。

2 个答案:

答案 0 :(得分:2)

您可以在scrollIntoView之后立即调用的componentDidUpdate之后使用render功能。

这是使用要滚动到的元素的ID的版本。您还可以存储元素的refs并按建议的方式执行。 (你无论如何都没有修改DOM)

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      media: ''
    }
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({
      media: event.target.value
    });
  }
  componentDidUpdate() {
    const element = document.getElementById(this.state.media);
    
    element.scrollIntoView({behavior: 'smooth'});
  }
  render() {
    return (
      <main>
        <select value={this.state.media} onChange={this.handleChange}>
          <option value="facebook">Facebook</option>
          <option value="youtube">Youtube</option>
        </select>
        <p id="facebook" className="social-media">Facebook</p>
        <p id="youtube" className="social-media">Youtube</p>
      </main>
    );
  }
}
ReactDOM.render(<App />, document.getElementById("root"));
.social-media {
  height: 100vh;
}

#facebook {
  margin-top: 100vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

您可能需要检查scrollIntoView的浏览器支持并包含polyfill

答案 1 :(得分:0)

有几种方法可以做到这一点: 其中一种方法是将componentWillReceiveProps生命周期事件中的状态更改视为:

componentWillReceiveProps(nextProp, nextState){
   //considering only first case here
   if (nextState.facebookFields== true && youtubeFields ==true){
      setTimeout(function(){
         let objControl=document.getElementById("theIdOfTheElementToBeRendered");
         objControl.scrollIntoView();
      },500)
   }
}

如上所述,我使用了setTimeout,因为此时元素未呈现。一旦渲染发生,回调函数将被回调(我假设延迟500ms;你可以自己决定)。

我使用普通的旧JS滚动到元素。确保元素具有唯一ID。

希望这个答案可以帮到你。我愿意讨论。问候。