单击按钮将页面滚动到子React组件,点击

时间:2019-08-11 08:36:10

标签: reactjs react-native

我有一个父组件,该组件在标头下方呈现一个子组件。标题具有一个按钮,单击该按钮时应滚动到相应子组件的一部分。

现在,我正在尝试更改按钮单击的状态,并将此新状态作为道具从父级传递到子级组件。然后,在子组件中,我尝试使用向下传递的prop作为要滚动到的部分的标识符来运行scroll()函数。

父组件:

 handleSelected = event => {
  this.setState({ selected: event.currentTarget.value });
 };

 <Button value="sectionOne" onClick={this.handleSelected} />

 <Child loadSelected={() => this.state.selected}</Child>

子组件:

  ComponentDidMount() {
   let selected = this.props.loadSelected();
   this.handleNavigate(selected);
  }

  handleNavigate = section => {
    let el = document.getElementById(section);
    window.scrollTo({
      behavior: "smooth",
      left: 0,
      top: el.offsetTop
    });
  };
  ....
  ....
  ....
  <div id="sectionOne" />

1 个答案:

答案 0 :(得分:2)

直接与DOM中的元素进行交互时,通常需要这样做via refs,而不是通过诸如getElementById()querySelectorAll()之类的方法从DOM查询元素等

您可以通过多种方式将refs集成到应用程序中以实现所需的功能-一种方法是为每个部分创建一个ref,并将每个部分及其相应的ref存储在父级中(标题?)组件,然后从父级而不是从子级handleNavigate(),如下所示:

class Parent extends React.Component {

  constructor(props) {
    super(props)

    /* Mock sections data */
    this.sections = [
    {
      name : "Foo",
      color: "pink",
      ref : React.createRef() /* Ref per section */
    },
    {
      name : "Bar",
      color: "lightblue",
      ref : React.createRef()
    },
    {
      name : "Cat",
      color: "lightgreen",
      ref : React.createRef()
    }];
  }

  /* Move into parent/header */
  handleNavigate = section => {

    /* 
    Access the "current element" of this sections ref. 
    Treat this as the element of the div for this section.
    */
    let el = section.ref.current;

    window.scrollTo({
      behavior: "smooth",
      left: 0,
      top: el.offsetTop
    });
  };

  render() {
    return (
        <div>
        <nav>
        <h2>Menu</h2>
        { 
            this.sections.map(section => 
            <button onClick={() => this.handleNavigate(section)}>
            {section.name}
            </button>)
        }
        </nav>
        <div>
        { this.sections.map(section => <Child section={section} />)}
        </div>
      </div>
    )
  }
}

class Child extends React.Component {
    render() {

    const { section } = this.props;
    const style = { 
        padding:"15rem 0", background : section.color 
    };

    return <div ref={ section.ref } style={ style }>
        Section for { section.name }
    </div>
  }
}

引用提供了一种与真实DOM元素进行交互的可靠方式,该元素表示组件渲染结果的一部分。在上面的代码中,ref与Child的div相关联。 ref的current字段提供对该孩子div的实际DOM元素的访问,可以将其传递给scrollTo()方法以实现您想要的平滑滚动动画。

有关此方法的有效示例,see this fiddle。希望有帮助!