我有一个问题,当导航到另一个页面,它的位置将保持像之前的页面。所以它不会自动滚动到顶部。 我也试过使用window。onChange路由器上的scrollTo(0,0)。我还使用了scrollBehavior来修复这个问题,但它没有工作。对此有什么建议吗?


当前回答

反应16.8 + 如果你正在运行React 16.8+,这是一个简单的处理组件,它会在每个导航中向上滚动窗口: 这是scrollToTop.js组件

import { useEffect } from "react";
import { useLocation } from "react-router-dom";

export default function ScrollToTop() {
  const { pathname } = useLocation();

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

  return null;
}

然后在应用程序的顶部渲染它,但在路由器下面 这是在app.js中

import ScrollToTop from "./scrollToTop";

function App() {
  return (
    <Router>
      <ScrollToTop />
      <App />
    </Router>
  );
}

或者在index.js中

import ScrollToTop from "./scrollToTop";

ReactDOM.render(
    <BrowserRouter>
        <ScrollToTop />
        <App />
    </BrowserRouter>
    document.getElementById("root")
);

其他回答

这个答案只适用于v4版本,而不适用于后续版本。

React Router v4的文档包含了用于滚动恢复的代码示例。下面是他们的第一个代码示例,它作为一个全站解决方案,当页面导航到“滚动到顶部”:

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

  render() {
    return this.props.children
  }
}

export default withRouter(ScrollToTop)

然后在你的应用程序的顶部渲染它,但在路由器下面:

const App = () => (
  <Router>
    <ScrollToTop>
      <App/>
    </ScrollToTop>
  </Router>
)

// or just render it bare anywhere you want, but just one :)
<ScrollToTop/>

^直接从文档中复制

显然,这适用于大多数情况,但是关于如何处理选项卡接口以及为什么没有实现通用解决方案还有更多内容。

2021年(React 16) -基于@Atombit的评论

下方卷轴向上,还保留了历史卷轴位置。

function ScrollToTop() {
  const history = useHistory()
  useEffect(() => {
    const unlisten = history.listen((location, action) => {
      if (action !== 'POP') {
        window.scrollTo(0, 0)
      }
    })
    return () => unlisten()
  }, [])
  return (null)
}

用法:

<Router>
  <ScrollToTop />
  <Switch>
    <Route path="/" exact component={Home} />
  </Switch>
</Router>

我在我的项目中使用了Typescript。这招对我很管用:

  // ScrollToTop.tsx
import {useEffect, useRef} from 'react'
import {withRouter} from 'react-router-dom'

const ScrollToTopComponent = () => {
  const mounted = useRef(false)

  useEffect(() => {
    if (!mounted.current) {
      //componentDidMount
      mounted.current = true
    } else {
      //componentDidUpdate
      window.scrollTo(0, 0)
    }
  })

  return null
}

export const ScrollToTop = withRouter(ScrollToTopComponent)



// usage in App.tsx
export default function App() {
  return (
     <Router>
        <ScrollToTop />
        <OtherRoutes />
     </Router>
  )
}

我的申请也遇到了同样的问题。使用下面的代码片段可以帮助我在单击下一个按钮时滚动到页面顶部。

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

然而,在浏览器返回时,这个问题仍然存在。经过大量的尝试,我意识到这是因为浏览器窗口的历史对象,它有一个属性scrollRestoration被设置为auto。将此设置为手动解决了我的问题。

function scrollToTop() {
    window.scrollTo(0, 0)
    if ('scrollRestoration' in history) {
        history.scrollRestoration = 'manual';
    }
}

<Router onUpdate= {scrollToTop} history={browserHistory}>
....
</Router>

对于较小的应用程序,有1-4个路由,你可以尝试用#id重定向到顶部DOM元素,而不仅仅是一个路由。这样就不需要在ScrollToTop或使用生命周期方法中包装路由。