在导航更改时滚动恢复到顶部

Posted

技术标签:

【中文标题】在导航更改时滚动恢复到顶部【英文标题】:Scroll restore to top on navigation change 【发布时间】:2019-08-02 08:58:21 【问题描述】:

我在使用 react-router 导航时遇到滚动问题。

当我导航到不同的组件时,它会保持上次导航的滚动位置。但是,我希望它在导航更改时恢复并从顶部开始。

 class App extends Component
  render() 
   return(
    <BrowserRouter onUpdate=() => window.scrollTo(0, 0) history=createBrowserHistory()>
      <div style=display: 'flex'>
        <div className='navBar'>
          <ul style=listStyleType: 'none'>
            <li><Link to='/'>Home</Link></li>
            <li><Link to='/towns'>Towns</Link></li>
            <li><Link to='/pubs'>Pubs</Link></li>
            <li><Link to='/venues'>Venues</Link></li>
            <li><Link to='/cinemas'>Cinemas</Link></li>

          </ul>
        </div>

        <div style=flex:1, padding:'0px'>
          routes.map((route) => (
            <Route
              key=route.path
              path=route.path
              exact=route.exact
              component=route.main
              />
            ))
          </div>
        </div>
      </BrowserRouter>
     )
   
 

但是它不起作用。我感觉问题出在我的导航风格上,而不是 window.scrollTo() sn-p。

【问题讨论】:

【参考方案1】:

据我所知,由于 react-router v4,BrowserRouter 没有 onUpdate 功能。

实现它的几种方法。这将是最简单的...

components/ScrollIntoView.js

import  PureComponent  from "react";
import  withRouter  from "react-router-dom";

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

  componentDidUpdate = prevProps => 
    if (this.props.location.pathname !== prevProps.location.pathname) window.scrollTo(0, 0);
  ;

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


export default withRouter(ScrollIntoView);

routes/index.js

import React from "react";
import  BrowserRouter, Route, Switch  from "react-router-dom";
import Links from "../components/Links";
import Home from "../components/Home";
import About from "../components/About";
import Contact from "../components/Contact";
import ScrollIntoView from "../components/ScrollIntoView";

export default () => (
  <BrowserRouter>
    <div>
      <ScrollIntoView>
        <Links />
        <Switch>
          <Route exact path="/" component=Home />
          <Route path="/about" component=About />
          <Route path="/contact" component=Contact />
        </Switch>
        <Links />
      </ScrollIntoView>
    </div>
  </BrowserRouter>
);

或者你可以在这里找到另一种方法:Scroll to the top of the page after render in react.js

【讨论】:

优秀的@Matt Carlotta。工作完美。唯一我可能想要改变的是,以某种方式使它,所以如果我再次点击以前的导航,让它记住我在哪里。但是,目前这不是一个大问题,您的回答已经达到了目标。谢谢。 这只有在第一次访问页面时才有效,如何做到每次都这样做?提前谢谢你 这个答案相当陈旧,并且使用 location 对象而不是 location.pathname 字符串包含错误。也就是说,我已经更新了答案,但是,如果可能的话,我强烈建议使用 react-router-dom 的 useLocation 钩子和 useEffect【参考方案2】:

我使用 React hooks 的解决方案

import  useEffect, useRef  from 'react';
import  withRouter  from 'react-router-dom';
import PropTypes from 'prop-types';

const ScrollIntoView = ( children, location ) => 
  const prevLocation = useRef();

  useEffect(() => 
    if (prevLocation.current !== location.pathname) 
      window.scrollTo(0, 0);
      prevLocation.current = location.pathname;
    
  , [location]);

  return children;
;

ScrollIntoView.propTypes = 
  children: PropTypes.node,
  location: PropTypes.object
;

export default withRouter(ScrollIntoView);

【讨论】:

useLocation() 而不是 withRouter 如果你真的想保持一切挂钩方式

以上是关于在导航更改时滚动恢复到顶部的主要内容,如果未能解决你的问题,请参考以下文章

滚动时如何让侧边栏对齐到顶部?

页面更改时的滚动恢复未完全滚动到顶部

底部对齐的导航棒滚动到顶部

当导航条滚动到顶部时固定到顶部

在顶部添加新项目后,回收器视图未滚动到顶部,因为尚未发生对列表适配器的更改

更改路线不会在新页面中滚动到顶部