我有一个问题,当导航到另一个页面,它的位置将保持像之前的页面。所以它不会自动滚动到顶部。 我也试过使用window。onChange路由器上的scrollTo(0,0)。我还使用了scrollBehavior来修复这个问题,但它没有工作。对此有什么建议吗?
当前回答
这是另一种方法。
对于react-router v4,您还可以以以下方式将侦听器绑定到历史事件中的change:
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'));
如果点击链接改变了路由,那么没有setimmediation(),滚动级别也会被设置为0,但是如果用户在浏览器上按下后退按钮,那么它将不起作用,因为浏览器在按下后退按钮时手动将滚动级别重置到上一个级别,所以通过使用setimmediation(),我们使我们的函数在浏览器完成重置滚动级别后执行,从而给我们提供了预期的效果。
其他回答
对于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
我想把我的解决方案分享给那些正在使用react-router-dom v5的人,因为这些v4解决方案中没有一个对我有用。
解决我的问题是安装react-router-scroll-top,并将包装器放在<App />中,如下所示:
const App = () => (
<Router>
<ScrollToTop>
<App/>
</ScrollToTop>
</Router>
)
就是这样!它工作!
我发现ReactDOM.findDomNode(this). scrollintoview()正在工作。我把它放在componentDidMount()中。
对我来说,是窗户。scrollTo(0,0)和document.documentElement。scrollTo(0,0)没有在我的所有屏幕上工作(只在一个屏幕上工作)。
然后,我意识到我的屏幕的溢出(滚动是允许的)不在窗口(因为我们有一些静态点,所以我们把溢出: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")转到一条新路线时,我的屏幕会转到顶部
2021年8月,
而不是在每个页面都这样做,你可以在App.js中这样做
import { useLocation } from "react-router-dom";
const location = useLocation();
useEffect(() => {
window.scrollTo(0,0);
}, [location]);
在useEffect中设置位置将确保每次路径更改时滚动到顶部。