我有一个问题,当导航到另一个页面,它的位置将保持像之前的页面。所以它不会自动滚动到顶部。 我也试过使用window。onChange路由器上的scrollTo(0,0)。我还使用了scrollBehavior来修复这个问题,但它没有工作。对此有什么建议吗?
当前回答
钩子是可组合的,从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]);
};
其他回答
我的申请也遇到了同样的问题。使用下面的代码片段可以帮助我在单击下一个按钮时滚动到页面顶部。
<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>
这有点老套(但很有效):我只是添加
Window. ScrollTo (0, 0);
呈现();
对于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上,我们可以检查位置路径名何时发生变化,并将其与路径道具匹配,如果满足,则恢复窗口滚动。
这个方法最酷的地方在于,我们可以有恢复滚动的路由和不恢复滚动的路由。
下面是一个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;
从上面的代码中,有趣的是,只有在导航到/关于或/另一个页面时,才会执行滚动到顶部的操作。然而,当进行/没有滚动恢复将发生。
整个代码库可以在这里找到:https://github.com/rizedr/react-router-scroll-top
render() {
window.scrollTo(0, 0)
...
}
在道具没有改变和componentDidUpdate()没有触发的情况下,这是一个简单的解决方案。
2022年11月更新
在react最新版本18.2.0和react-router-dom 6.4.3中没有任何工作。所以我实现了这个。为我工作。希望这对大家有帮助。
ScrollToTop.js
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
export default function ScrollToTop() {
const { pathname } = useLocation();
useEffect(() => {
const body = document.querySelector('#root');
body.scrollIntoView({
behavior: 'smooth'
}, 500)
}, [pathname]);
return null;
}
然后在index.js或App.js中导入并添加到浏览器路由器,在那里定义路由。
import { BrowserRouter, Routes, Route } from "react-router-dom";
import ScrollToTop from "./ScrollToTop";
function App() {
return (
<div>
<BrowserRouter>
<ScrollToTop />
<Routes>
//your routes
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
(注意:确保index.html div id="root"。)
推荐文章
- 这个“react-scripts eject”命令是做什么的?
- 如何为Firebase构建云函数,以便从多个文件部署多个函数?
- 如何发送推送通知到web浏览器?
- AngularJS:工厂和服务?
- js:将一个组件包装成另一个组件
- 父ng-repeat从子ng-repeat的访问索引
- JSHint和jQuery: '$'没有定义
- 模仿JavaScript中的集合?
- 用JavaScript验证电话号码
- 如何在HTML5中改变视频的播放速度?
- 谷歌地图API v3:我可以setZoom后fitBounds?
- ES6/2015中的null安全属性访问(和条件赋值)
- 与push()相反;
- JS字符串“+”vs concat方法
- AngularJS使用ng-class切换类