我有个问题,我不知道怎么解决。 在我的react组件中,我在底部显示了一个很长的数据列表和一些链接。 点击任何链接后,我在列表中填充了新的链接集合,需要滚动到顶部。

问题是-如何滚动到顶部后,新的集合呈现?

'use strict';

// url of this component is #/:checklistId/:sectionId

var React = require('react'),
  Router = require('react-router'),
  sectionStore = require('./../stores/checklist-section-store');


function updateStateFromProps() {
  var self = this;
  sectionStore.getChecklistSectionContent({
    checklistId: this.getParams().checklistId,
    sectionId: this.getParams().sectionId
  }).then(function (section) {
    self.setState({
      section,
      componentReady: true
    });
  });

    this.setState({componentReady: false});
 }

var Checklist = React.createClass({
  mixins: [Router.State],

  componentWillMount: function () {
    updateStateFromProps.call(this);
  },

  componentWillReceiveProps(){
    updateStateFromProps.call(this);
   },

render: function () {
  if (this.state.componentReady) {
    return(
      <section className='checklist-section'>
        <header className='section-header'>{ this.state.section.name }   </header>
        <Steps steps={ this.state.section.steps }/>
        <a href=`#/${this.getParams().checklistId}/${this.state.section.nextSection.Id}`>
          Next Section
        </a>
      </section>
    );
    } else {...}
  }
});

module.exports = Checklist;

当前回答

这段代码将导致滚动的平滑行为:

<div onClick={() => {
   ReactDOM.findDOMNode(this.headerRef)
      .scrollIntoView({behavior: "smooth"});
                }} 
  className='go-up-button' >
</div>

你可以在scrollIntoView()中传递其他参数 可以使用以下语法:

element.scrollIntoView();
element.scrollIntoView(alignToTop); // Boolean parameter
element.scrollIntoView(scrollIntoViewOptions); // Object parameter

alignToTop可选 为布尔值:

If true, the top of the element will be aligned to the top of the visible area of the scrollable ancestor. Corresponds to scrollIntoViewOptions: {block: "start", inline: "nearest"}. This is the default value.
If false, the bottom of the element will be aligned to the bottom of the visible area of the scrollable ancestor. Corresponds to scrollIntoViewOptions: {block: "end", inline: "nearest"}.

scrollIntoViewOptions可选 是具有以下属性的对象:

*behavior* Optional
    Defines the transition animation.
    One of "auto", "instant", or "smooth". Defaults to "auto".
*block* Optional
    One of "start", "center", "end", or "nearest". Defaults to "center".
*inline* Optional
    One of "start", "center", "end", or "nearest". Defaults to "nearest".

更多细节可以在这里找到:MDN文档

其他回答

这里还有另一种方法,它允许你选择你希望窗口滚动位置重置到的安装组件,而不需要大量复制ComponentDidUpdate/ComponentDidMount。

下面的例子是用ScrollIntoView()包装Blog组件,这样当Blog组件被挂载时,如果路由改变了,那么HOC的ComponentDidUpdate将更新窗口滚动位置。

你可以很容易地将它包裹在整个应用程序中,这样在任何路由改变时,它都会触发一个窗口重置。

ScrollIntoView.js

import React, { Component } from 'react';
import { withRouter } from 'react-router';

export default WrappedComponent => {
  class ResetWindowScroll extends Component {
    componentDidUpdate = (prevProps) => {
      if(this.props.location !== prevProps.location) window.scrollTo(0,0);
    }

    render = () => <WrappedComponent {...this.props} />
  }
  return withRouter(ResetWindowScroll);
}

Routes.js

import React from 'react';
import { Route, IndexRoute } from 'react-router';

import App from '../components/App';
import About from '../components/pages/About';
import Blog from '../components/pages/Blog'
import Index from '../components/Landing';
import NotFound from '../components/navigation/NotFound';
import ScrollIntoView from '../components/navigation/ScrollIntoView';

 export default (
    <Route path="/" component={App}>
        <IndexRoute component={Index} />
        <Route path="/about" component={About} /> 
        <Route path="/blog" component={ScrollIntoView(Blog)} />
        <Route path="*" component={NotFound} />
    </Route>
);

上面的示例工作得很好,但是如果您已经迁移到react-router-dom,那么您可以通过创建一个封装组件的HOC来简化上面的示例。

同样,您也可以轻松地将它包装在您的路由上(只需将componentDidMount方法更改为上面编写的componentDidUpdate方法示例代码,以及使用withRouter包装ScrollIntoView)。

容器/ ScrollIntoView.js

import { PureComponent, Fragment } from "react";

class ScrollIntoView extends PureComponent {
  componentDidMount = () => window.scrollTo(0, 0);

  render = () => this.props.children
}

export default ScrollIntoView;

组件/ Home.js

import React from "react";
import ScrollIntoView from "../containers/ScrollIntoView";

export default () => (
  <ScrollIntoView>
    <div className="container">
      <p>
        Sample Text
      </p>
    </div>
  </ScrollIntoView>
);

点击后出现的页面,只需在其中写入即可。

  componentDidMount() {
    window.scrollTo(0, 0);
  } 

所有的解决方案都谈论在componentDidMount或componentDidUpdate上添加滚动,但使用DOM。

我做了所有这些,但都没用。

所以我找到了另一种适合我的方法。

添加 componentDidUpdate(){窗口。scrollTo(0,0)} 在header中,我的是<Switch></Switch>元素。只要在应用里免费就行了。

我还发现了一些关于ScrollRestoration的东西,但我现在很懒。现在就用“DidUpdate”的方式吧。

最后. .我使用:

componentDidMount() {
  window.scrollTo(0, 0)
}

编辑:React v16.8+

useEffect(() => {
  window.scrollTo(0, 0)
}, [])

我已经尝试过@sledgeweight解决方案,但它并不适用于某些视图。但是添加setTimeout似乎可以完美地工作。以防有人遇到和我一样的问题。下面是我的代码。

import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'

const ScrollToTop = () => {
    const { pathname } = useLocation()
    useEffect(() => {
        console.log(pathname)
        /* settimeout make sure this run after components have rendered. This will help fixing bug for some views where scroll to top not working perfectly */
        setTimeout(() => {
            window.scrollTo({ top: 0, behavior: 'smooth' })
        }, 0)
    }, [pathname])
    return null
}

export default ScrollToTop

在AppRouter.js中使用它

<Router>
    <ScrollToTop/>
    <App>
</Router>