使用 React Router 强制执行 scrollToTop 行为

Enforcing scrollToTop behavior using React Router

我希望在转换时将用户的滚动位置默认设置为页面顶部。

例如,单击页脚上的 <Link> 元素会将用户推入一直向下滚动的视图,即页脚所在的位置。

是否有一个选项可以将所有转换设置为从顶部显示新组件?

您需要导入 scroll-behavior 库,专为与 React 路由器一起使用而设计。使用方法如下:

import createHistory from 'history/lib/createBrowserHistory';
import useScrollToTop from 'scroll-behavior/lib/useScrollToTop';

const history = useScrollToTop(createHistory)();

然后将 history 对象作为 history 道具传递给您的 Router

上面的代码片段 - 修改为导入 useScrollToTop 而不是 useStandardScroll - 取自此处: https://github.com/rackt/scroll-behavior

React Router 版本 <4

您也可以简单地向 <Router> 添加一个 onUpdate 属性,如下所示:

<Router onUpdate={() => window.scrollTo(0, 0)} history={history}>
  // routes
</Router>

React Router 版本 4

在新的 React Router 版本中,您可以像这样创建一个 ScrollToTop 组件(改编自 docs here):

// ScrollToTop.js    
import React, {Component} from 'react'
import {withRouter} from 'react-router-dom'

class ScrollToTop extends Component {
  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      window.scrollTo(0, 0)
    }
  }

  render() {
    return <div>{this.props.children}</div>
  }
}

export default withRouter(ScrollToTop)

然后通过将它添加到 BrowserRouter/Router 组件下方来使用它,如下所示:

// App.js
import React, {Component} from 'react';
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
import ScrollToTop from './ScrollToTop'

const App = () => (
  <Router>
    <ScrollToTop>
      <Route exact path="/" component={Home} />
      <Route path="/about" component={About} />
      <Link to="/">Home</Link>{' '}
      <Link to="/about">About</Link>
    </ScrollToTop>
  </Router>
)

如果您遵循了 React 路由器文档(和 Sia 的回答)但发现自己遇到此错误:

Invariant Violation: ScrollToTop.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.

尝试将 ScrollToTop 中的所有内容包装成一个 <div>:

<Router>
  <ScrollToTop>
    <div>
      <Route exact path="/" component={Home} />
      <Route path="/about" component={About} />
      <Link to="/">Home</Link>{' '}
      <Link to="/about">About</Link>
    </div>
  </ScrollToTop>
</Router>