导航到另一个页面时遇到问题,它的位置将保持与之前的页面一样。所以它不会自动滚动到顶部。我也试过window.scrollTo(0, 0)
在onChange
路由器上使用。我也曾经scrollBehavior
解决过这个问题,但没有用。对此有何建议?
react-router 在每次转换时滚动到顶部
IT技术
javascript
reactjs
react-router
react-router-redux
2021-02-02 01:05:51
6个回答
但课程是如此 2018
使用 React Hooks 实现 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 也可以实现为一个包装组件:
滚动到顶部.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>
此答案仅适用于 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/>
显然这适用于大多数情况,但还有更多关于如何处理选项卡式界面以及为什么尚未实施通用解决方案的内容。
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")
);
此答案适用于遗留代码,适用于路由器 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;
}
}
您可以添加到 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
可能更适合您。