【问题标题】:react-router scroll to top on every transitionreact-router 在每次转换时滚动到顶部
【发布时间】:2021-09-22 10:22:56
【问题描述】:

我在导航到另一个页面时遇到问题,它的位置将保持与之前的页面相同。所以它不会自动滚动到顶部。 我还尝试在onChange 路由器上使用window.scrollTo(0, 0)。我也使用scrollBehavior 解决了这个问题,但没有奏效。对此有何建议?

【问题讨论】:

  • 新路由组件的componentDidMount里的逻辑你能不做吗?
  • 只需在要移动到的组件的componentDidMount 中添加document.body.scrollTop = 0;
  • @Kujira 我已经在 componentDidMount() 中添加了 scrollTo 但它没有用。
  • @JohnRuddell 那也不行。
  • 这里有一些很好的解决方案,但是如果点击一个带有锚 id 的链接怎么办?

标签: javascript reactjs react-router react-router-redux


【解决方案1】:

但是 2018 年的课程是如此

使用 React Hooks 实现 ScrollToTop

ScrollToTop.js

import { useEffect } from 'react';
import { withRouter } from 'react-router-dom';

function ScrollToTop({ history }) {
  useEffect(() => {
    const unlisten = history.listen(() => {
      window.scrollTo(0, 0);
    });
    return () => {
      unlisten();
    }
  }, []);

  return (null);
}

export default withRouter(ScrollToTop);

用法:

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

ScrollToTop 也可以实现为包装组件:

ScrollToTop.js

import React, { useEffect, Fragment } from 'react';
import { withRouter } from 'react-router-dom';

function ScrollToTop({ history, children }) {
  useEffect(() => {
    const unlisten = history.listen(() => {
      window.scrollTo(0, 0);
    });
    return () => {
      unlisten();
    }
  }, []);

  return <Fragment>{children}</Fragment>;
}

export default withRouter(ScrollToTop);

用法:

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

【讨论】:

  • 迄今为止我在互联网上看到的最佳解决方案。我只是有点困惑为什么 react-router 项目没有将属性 scrollToTop 添加到 &lt;Route&gt;。这似乎是一个非常常用的功能。
  • 你应该检查action !== 'POP'。侦听器接受动作作为第二个参数
  • 另外,你可以只使用 useHistory hook 而不是 withRouter HOC
  • 我需要将history添加到useEffect的依赖列表中
  • 对于 TypeScript 用户,history 属性的正确类型是 History from import { History } from "history";
【解决方案2】:

此答案仅适用于 v4,不适用于更高版本。

React Router v4 的文档包含用于滚动恢复的 code samples。这是他们的第一个代码示例,当页面被导航到时,它用作“滚动到顶部”的站点范围解决方案:

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/>

^ copied directly from the documentation

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

【讨论】:

  • 您还应该在滚动到顶部的同时重置键盘焦点。我写了一个东西来处理它:github.com/oaf-project/oaf-react-router
  • 这个来自文档Because browsers are starting to handle the “default case” and apps have varying scrolling needs (like this website!), we don’t ship with default scroll management. This guide should help you implement whatever scrolling needs you have. 的摘录让我很难过,因为他们继续提供代码示例的所有选项实际上都可以通过属性设置烘焙到控件中,并带有一些围绕默认行为的约定然后可以更改。这感觉超级hacky和未完成,恕我直言。意味着只有高级反应开发人员才能正确进行路由并且没有#pitOfSuccess
  • oaf-react-router 似乎解决了所有work-arounds 这里都忽略的重要可访问性问题。 +100 @danielnixon
  • ScrollToTop 未定义。如何在 App.js 中导入它?从 './ScrollToTop' 导入 ScrollToTop 不起作用。
  • 你应该检查action !== 'POP'。侦听器接受动作作为第二个参数
【解决方案3】:

React 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")
);

【讨论】:

  • 谢谢,这是我认为最好的解决方案!
  • 是的,这是一个合适的解决方案,适用于使用钩子的反应应用程序。
  • 这之前对我有用,但它已经停止工作。有谁知道为什么?我什至没有更新反应路由器!提前谢谢你
【解决方案4】:

此答案适用于遗留代码,路由器 v4+ 检查其他答案

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

如果它不起作用,你应该找出原因。也在componentDidMount里面

document.body.scrollTop = 0;
// or
window.scrollTo(0,0);

你可以使用:

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

您可以添加一些标志,例如“scrolled = false”,然后在更新中:

componentDidUpdate() {
  if(this.scrolled === false){
    window.scrollTo(0,0);
    scrolled = true;
  }
}

【讨论】:

  • 我已经更新了没有 getDomNode 的答案,因为事实上我从来不用它来滚动到顶部。我刚刚使用window.scrollTo(0,0);
  • onUpdate 钩子在 react-router v4 中已被弃用 - 只是想指出这一点
  • @DragosRizescu 有关在不使用 onUpdate 钩子的情况下使用此方法的任何指导?
  • @MattVoda 您可以监听历史本身的变化,查看示例:github.com/ReactTraining/history
  • @MattVoda 在下面写了一个关于如何使用 react-router-v4 实现这一目标的答案
【解决方案5】:

一个可以添加到 Route 组件的 React Hook。使用 useLayoutEffect 而不是自定义监听器。

import React, { useLayoutEffect } from 'react';
import { Switch, Route, useLocation } from 'react-router-dom';

export default function Routes() {
  const location = useLocation();
  // Scroll to top if path changes
  useLayoutEffect(() => {
    window.scrollTo(0, 0);
  }, [location.pathname]);

  return (
      <Switch>
        <Route exact path="/">

        </Route>
      </Switch>
  );
}

更新:更新为使用useLayoutEffect 而不是useEffect,以减少视觉卡顿。大致意思是:

  • useEffect:渲染组件 -> 绘制到屏幕 -> 滚动到顶部(运行效果)
  • useLayoutEffect: 渲染组件 -> 滚动到顶部(运行效果)-> 绘制到屏幕

根据您是否正在加载数据(想想微调器)或是否有页面过渡动画,useEffect 可能更适合您。

【讨论】:

    【解决方案6】:

    对于react-router v4,这里有一个实现滚动恢复的create-react-app:http://router-scroll-top.surge.sh/

    要实现这一点,您可以创建装饰 Route 组件并利用生命周期方法:

    import React, { Component } from 'react';
    import { Route, withRouter } from 'react-router-dom';
    
    class ScrollToTopRoute extends Component {
      componentDidUpdate(prevProps) {
        if (this.props.path === this.props.location.pathname && this.props.location.pathname !== prevProps.location.pathname) {
          window.scrollTo(0, 0)
        }
      }
    
      render() {
        const { component: Component, ...rest } = this.props;
    
        return <Route {...rest} render={props => (<Component {...props} />)} />;
      }
    }
    
    export default withRouter(ScrollToTopRoute);
    

    componentDidUpdate 上,我们可以检查位置路径名何时更改并将其与path 属性匹配,如果满足,则恢复窗口滚动。

    这种方法最酷的地方在于,我们可以有恢复滚动的路由和不恢复滚动的路由。

    这是一个App.js 示例,说明如何使用上述内容:

    import React, { Component } from 'react';
    import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
    import Lorem from 'react-lorem-component';
    import ScrollToTopRoute from './ScrollToTopRoute';
    import './App.css';
    
    const Home = () => (
      <div className="App-page">
        <h2>Home</h2>
        <Lorem count={12} seed={12} />
      </div>
    );
    
    const About = () => (
      <div className="App-page">
        <h2>About</h2>
        <Lorem count={30} seed={4} />
      </div>
    );
    
    const AnotherPage = () => (
      <div className="App-page">
        <h2>This is just Another Page</h2>
        <Lorem count={12} seed={45} />
      </div>
    );
    
    class App extends Component {
      render() {
        return (
          <Router>
            <div className="App">
              <div className="App-header">
                <ul className="App-nav">
                  <li><Link to="/">Home</Link></li>
                  <li><Link to="/about">About</Link></li>
                  <li><Link to="/another-page">Another Page</Link></li>
                </ul>
              </div>
              <Route exact path="/" component={Home} />
              <ScrollToTopRoute path="/about" component={About} />
              <ScrollToTopRoute path="/another-page" component={AnotherPage} />
            </div>
          </Router>
        );
      }
    }
    
    export default App;
    

    从上面的代码中,有趣的是,只有当导航到/about/another-page 时,才会执行滚动到顶部的操作。但是,当继续 / 时,不会发生滚动恢复。

    整个代码库可以在这里找到:https://github.com/rizedr/react-router-scroll-top

    【讨论】:

    • 正是我想要的!我必须在 ScrollToTopRoute 的 componentDidMount 中添加 scrollTo,因为我的路由包裹在 Switch 组件中(我还删除了 if,因为我希望它在每次安装时触发)
    • 在你的 ScrollToTopRoute 的渲染中,你不需要指定 render={props => ()}。只需在路线中使用 {...rest} 即可。
    • 这个答案为我提供了实现解决方案和修复错误的所有工具。非常感谢。
    • 它没有完全工作。如果您点击项目链接,则默认打开Home。现在滚动到Home 的底部,然后转到“AnotherPage”并且不要滚动。现在如果您再次访问Home,此页面将滚动到顶部。但根据您的回答,home 页面应该保持滚动状态。
    • } exact={true}/> 请问我该怎么做在 ScrollToTopRoute 组件上使用 title 属性?
    【解决方案7】:

    值得注意的是onUpdate={() =&gt; window.scrollTo(0, 0)} 方法已经过时了。

    这是 react-router 4+ 的简单解决方案。

    const history = createBrowserHistory()
    
    history.listen(_ => {
        window.scrollTo(0, 0)  
    })
    
    <Router history={history}>
    

    【讨论】:

    • 如果使用历史,这应该是正确的答案。它涵盖了所有可能的情况,包括单击指向您当前所在页面的链接。我发现的唯一问题是 scrollTo 没有触发,需要包裹在 setTimeout(window.scrollTo(0, 0),0);我仍然不明白为什么,但是嘿嘿
    • 当您在我们的网址末尾添加#? 时会遇到问题。在第一种情况下,您应该将 no 滚动到顶部,在第二种情况下,您根本不应该滚动
    • 很遗憾,这不适用于 BrowserRouter。
    【解决方案8】:

    React hooks 2020 :)

    import React, { useLayoutEffect } from 'react';
    import { useLocation } from 'react-router-dom';
    
    const ScrollToTop: React.FC = () => {
      const { pathname } = useLocation();
      useLayoutEffect(() => {
        window.scrollTo(0, 0);
      }, [pathname]);
    
      return null;
    };
    
    export default ScrollToTop;
    

    【讨论】:

    • 你能解释一下这部分吗? const ScrollToTop: React.FC = () =&gt; {我不明白ScrollToTop: React.FC是什么意思
    • 打字稿定义
    【解决方案9】:

    &lt;Router&gt;下面的一个组件中

    只需添加一个 React Hook(以防你不使用 React 类)

      React.useEffect(() => {
        window.scrollTo(0, 0);
      }, [props.location]);
    

    【讨论】:

      【解决方案10】:

      我的应用程序也遇到了同样的问题。使用下面的代码 sn-p 帮助我在单击下一个按钮时滚动到页面顶部。

      <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>
      

      【讨论】:

        【解决方案11】:

        我想与使用 react-router-dom v5 的人分享我的解决方案,因为这些 v4 解决方案都没有为我工作。

        解决我的问题的方法是安装 react-router-scroll-top 并将包装器放入 &lt;App /&gt; 中,如下所示:

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

        就是这样!成功了!

        【讨论】:

          【解决方案12】:

          Hooks 是可组合的,从 React Router v5.1 开始,我们有一个 useHistory() 钩子。因此,根据@zurfyx 的回答,我为此功能创建了一个可重用的钩子:

          // useScrollTop.ts
          import { useHistory } from 'react-router-dom';
          import { useEffect } from 'react';
          
          /*
           * Registers a history listener on mount which
           * scrolls to the top of the page on route change
           */
          export const useScrollTop = () => {
              const history = useHistory();
              useEffect(() => {
                  const unlisten = history.listen(() => {
                      window.scrollTo(0, 0);
                  });
                  return unlisten;
              }, [history]);
          };
          

          【讨论】:

          【解决方案13】:

          我的解决方案:我在屏幕组件中使用的一个组件(我希望滚动到顶部)。

          import { useLayoutEffect } from 'react';
          
          const ScrollToTop = () => {
              useLayoutEffect(() => {
                  window.scrollTo(0, 0);
              }, []);
          
              return null;
          };
          
          export default ScrollToTop;
          

          这会在返回时保留滚动位置。 使用 useEffect() 对我来说是个问题,当返回文档时,文档会滚动到顶部,并且在已经滚动的文档中更改路径时还会产生闪烁效果。

          【讨论】:

          • 我认为这是更清洁的解决方案,也是最有效的解决方案。
          【解决方案14】:

          这是我的方法,基于其他人在之前的帖子中所做的。想知道这是否是 2020 年使用位置作为依赖项来防止重新渲染的好方法?

          import React, { useEffect } from 'react';
          import { useLocation } from 'react-router-dom';
          
          function ScrollToTop( { children } ) {
              let location = useLocation();
          
              useEffect( () => {
                  window.scrollTo(0, 0);
              }, [ location ] );
          
              return children
          }
          

          【讨论】:

          【解决方案15】:

          2021 (React 16) - 基于来自 @Atombit 的 cmets

          下方滚动到顶部,但也保留历史滚动位置。

          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>
          

          【讨论】:

          • 我一直在寻找这个答案。但是,我的解决方案是检查操作是否为“PUSH”,这样 REPLACE 也不会触发滚动到顶部。
          【解决方案16】:

          利用钩子,您可以在代码库中的useEffect 中简单地插入window.scrollTo(0,0)。只需在您的应用中实现代码 sn-p,它就会在其窗口顶部加载每个页面。

          import { useEffect } from 'react';
          
          useEffect(() => {
             window.scrollTo(0, 0);
          }, []);
          

          【讨论】:

            【解决方案17】:

            2021 年 8 月

            而不是在每个页面都这样做,你可以在 App.js 中这样做

            import { useLocation } from "react-router-dom";
            
            const location = useLocation();
            useEffect(() => {
              window.scrollTo(0,0);
            }, [location]);
            

            useEffect 中设置位置将确保在每次路径更改时滚动到顶部。

            【讨论】:

            • 它对我有用
            【解决方案18】:

            我编写了一个名为withScrollToTop 的高阶组件。这个 HOC 有两个标志:

            • onComponentWillMount - 导航时是否滚动到顶部 (componentWillMount)
            • onComponentDidUpdate - 更新时是否滚动到顶部 (componentDidUpdate)。此标志在组件未卸载但发生导航事件的情况下是必需的,例如从/users/1/users/2

            // @flow
            import type { Location } from 'react-router-dom';
            import type { ComponentType } from 'react';
            
            import React, { Component } from 'react';
            import { withRouter } from 'react-router-dom';
            
            type Props = {
              location: Location,
            };
            
            type Options = {
              onComponentWillMount?: boolean,
              onComponentDidUpdate?: boolean,
            };
            
            const defaultOptions: Options = {
              onComponentWillMount: true,
              onComponentDidUpdate: true,
            };
            
            function scrollToTop() {
              window.scrollTo(0, 0);
            }
            
            const withScrollToTop = (WrappedComponent: ComponentType, options: Options = defaultOptions) => {
              return class withScrollToTopComponent extends Component<Props> {
                props: Props;
            
                componentWillMount() {
                  if (options.onComponentWillMount) {
                    scrollToTop();
                  }
                }
            
                componentDidUpdate(prevProps: Props) {
                  if (options.onComponentDidUpdate &&
                    this.props.location.pathname !== prevProps.location.pathname) {
                    scrollToTop();
                  }
                }
            
                render() {
                  return <WrappedComponent {...this.props} />;
                }
              };
            };
            
            export default (WrappedComponent: ComponentType, options?: Options) => {
              return withRouter(withScrollToTop(WrappedComponent, options));
            };
            

            使用它:

            import withScrollToTop from './withScrollToTop';
            
            function MyComponent() { ... }
            
            export default withScrollToTop(MyComponent);
            

            【讨论】:

              【解决方案19】:

              由于我使用功能组件,所以我设法实现它。

              import { useEffect } from 'react';
              import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom';
              
              function ScrollToTop() {
                  const { pathname } = useLocation();
              
                  useEffect(() => {
                      window.scrollTo(0, 0);
                  }, [pathname]);
              
                  return null;
              }
              
              const IndexRoutes = () => {
              
                  return (
                      <BrowserRouter>
                          <ScrollToTop />
                          <Routes>
                              <Route exact path="/">
                                  <Home /> 
                              </Route>
                              /* list other routes below */
                          </Routes>
                      </BrowserRouter>
                  );
              };
              
              export default IndexRoutes;
              

              您也可以参考以下链接中的代码

              https://reactrouter.com/web/guides/scroll-restoration

              【讨论】:

                【解决方案20】:

                对我来说,window.scrollTo(0, 0)document.documentElement.scrollTo(0, 0) 并不能在我的所有屏幕上运行(仅在 1 个屏幕上运行)。

                然后,我意识到我的屏幕溢出(允许滚动)不在window 中(因为我们有一些静态点,所以我们将overflow: auto 放在其他div 中)。

                我做了以下测试来实现这一点:

                useEffect(() => {
                  const unlisten = history.listen(() => {
                    console.log(document.documentElement.scrollTop)
                    console.log(window.scrollTop)
                    window.scrollTo(0, 0);
                  });
                  return () => {
                    unlisten();
                  }
                }, []);
                

                在所有日志中,我得到了 0。

                所以,我查找了滚动条放入哪个容器并输入了一个 id:

                <div id="SOME-ID">
                    ...
                </div>
                

                在我的 ScrollToTop 组件中我放了:

                useEffect(() => {
                  const unlisten = history.listen(() => {
                    window.scrollTo(0, 0);
                    document.getElementById("SOME-ID")?.scrollTo(0, 0)
                  });
                  return () => {
                    unlisten();
                  }
                }, []);
                

                现在,当我使用history.push("/SOME-ROUTE") 前往新路线时,我的屏幕会转到顶部

                【讨论】:

                  【解决方案21】:

                  这是另一种方法。

                  对于 react-router v4,您还可以通过以下方式绑定监听器以更改历史事件:

                  let firstMount = true;
                  const App = (props) => {
                      if (typeof window != 'undefined') { //incase you have server-side rendering too             
                          firstMount && props.history.listen((location, action) => {
                              setImmediate(() => window.scrollTo(0, 0)); // ive explained why i used setImmediate below
                          });
                          firstMount = false;
                      }
                  
                      return (
                          <div>
                              <MyHeader/>            
                              <Switch>                            
                                  <Route path='/' exact={true} component={IndexPage} />
                                  <Route path='/other' component={OtherPage} />
                                  // ...
                               </Switch>                        
                              <MyFooter/>
                          </div>
                      );
                  }
                  
                  //mounting app:
                  render((<BrowserRouter><Route component={App} /></BrowserRouter>), document.getElementById('root'));
                  

                  如果通过单击链接更改路线但如果用户按下浏览器上的后退按钮则滚动级别将设置为 0 而没有 setImmediate()当按下后退按钮时,通过使用setImmediate(),我们会在浏览器完成重置滚动级别后执行我们的函数,从而为我们提供所需的效果。

                  【讨论】:

                    【解决方案22】:

                    你可以使用 React 路由器 dom v4

                    创建一个如下所示的 scrollToTopComponent 组件

                    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)
                    

                    或者,如果您使用的是标签,请使用类似下面的标签

                    class ScrollToTopOnMount extends Component {
                        componentDidMount() {
                          window.scrollTo(0, 0)
                        }
                    
                        render() {
                          return null
                        }
                    }
                    
                    class LongContent extends Component {
                        render() {
                          <div>
                             <ScrollToTopOnMount/>
                             <h1>Here is my long content page</h1>
                          </div>
                        }
                    }
                    
                    // somewhere else
                    <Route path="/long-content" component={LongContent}/>
                    

                    希望这有助于更多关于滚动恢复的信息,请参阅 docs hare react router dom scroll restoration

                    【讨论】:

                      【解决方案23】:

                      在您的router.js 中,只需将此函数添加到router 对象中。这样就可以了。

                      scrollBehavior() {
                              document.getElementById('app').scrollIntoView();
                          },
                      

                      这样,

                      **Routes.js**

                      import vue from 'blah!'
                      import Router from 'blah!'
                      
                      let router = new Router({
                          mode: 'history',
                          base: process.env.BASE_URL,
                          scrollBehavior() {
                              document.getElementById('app').scrollIntoView();
                          },
                          routes: [
                                  { url: "Solar System" },
                                  { url: "Milky Way" },
                                  { url: "Galaxy" },
                          ]
                      });
                      

                      【讨论】:

                        【解决方案24】:

                        使用 useEffect() - 功能组件的解决方案

                         useEffect(() => {
                        window.history.scrollRestoration = 'manual';}, []);
                        

                        【讨论】:

                          【解决方案25】:

                          我唯一的解决方案是在每个文件中添加一行代码,例如:

                          import React from 'react';
                          const file = () => { document.body.scrollTop = 0; return( <div></div> ) }
                          

                          【讨论】:

                            【解决方案26】:

                            我在我的项目中使用了 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>
                              )
                            }
                            

                            【讨论】:

                              【解决方案27】:

                              我发现ReactDOM.findDomNode(this).scrollIntoView() 正在工作。我把它放在componentDidMount()里面。

                              【讨论】:

                              • 这是未记录的内部内容,可能会在不注意的情况下发生变化,您的代码将停止工作。
                              【解决方案28】:

                              对于具有 1-4 条路由的较小应用程序,您可以尝试使用 #id 重定向到顶部 DOM 元素而不只是一条路由来破解它。那么就不需要在 ScrollToTop 中包裹 Routes 或者使用生命周期方法了。

                              【讨论】:

                                【解决方案29】:

                                对于 react-router-dom V5 react-router-dom V5 scroll to top

                                    import React, { useEffect } from 'react';
                                import {
                                    BrowserRouter as Router,
                                    Switch,
                                    Route,
                                    Link,
                                    useLocation,
                                    withRouter
                                } from 'react-router-dom'
                                function _ScrollToTop(props) {
                                    const { pathname } = useLocation();
                                    useEffect(() => {
                                        window.scrollTo(0, 0);
                                    }, [pathname]);
                                    return props.children
                                }
                                const ScrollToTop = withRouter(_ScrollToTop)
                                function App() {
                                    return (
                                        <div>
                                            <Router>
                                                <ScrollToTop>
                                                    <Header />
                                                     <Content />
                                                    <Footer />
                                                </ScrollToTop>
                                            </Router>
                                        </div>
                                    )
                                }
                                

                                【讨论】:

                                • 通常,将您链接到的文档中的内容放入答案本身会很有帮助,以防目标更改或无法访问。不过,您可以保留链接,以供参考!
                                • @brandonscript 它已随内容更新。我放了链接,以便内容作者能够花时间编写内容而获得全部功劳,这将有助于其他人阅读整个内容。但是如果目的地改变了,你的权利也会有所帮助
                                【解决方案30】:
                                render() {
                                    window.scrollTo(0, 0)
                                    ...
                                }
                                

                                如果 props 未更改且 componentDidUpdate() 未触发,则可以是一个简单的解决方案。

                                【讨论】:

                                  猜你喜欢
                                  • 2022-08-05
                                  • 2021-01-29
                                  • 1970-01-01
                                  • 2022-01-09
                                  • 2018-04-28
                                  • 2020-10-01
                                  • 2018-12-03
                                  • 2021-08-12
                                  相关资源
                                  最近更新 更多