У меня проблема при переходе на другую страницу, ее позиция останется прежней. Таким образом, он не будет автоматически прокручиваться вверх. Я также попытался использовать window.scrollTo(0, 0)
на маршрутизаторе onChange. Я также использовал scrollBehavior, чтобы исправить эту проблему, но она не работала. Любое предложение об этом?
реагировать-роутер прокручивается вверх на каждый переход
Ответ 1
В документации для 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)
Затем отрисуйте его в верхней части приложения, но ниже Router:
const App = () => (
<Router>
<ScrollToTop>
<App/>
</ScrollToTop>
</Router>
)
// or just render it bare anywhere you want, but just one :)
<ScrollToTop/>
^ скопировано непосредственно из документации
Очевидно, что это работает в большинстве случаев, но есть больше о том, как работать с интерфейсами с вкладками и почему универсальное решение не реализовано.
Ответ 2
Этот ответ предназначен для устаревшего кода, поскольку маршрутизатор 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", а затем в update:
componentDidUpdate() {
if(this.scrolled === false){
window.scrollTo(0,0);
scrolled = true;
}
}
Ответ 3
но классы такие 2018
Реализация ScrollToTop с 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 также может быть реализован как компонент оболочки:
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>
Ответ 4
Для реактивного маршрутизатора v4 здесь создается приложение-реакция-приложение, которое обеспечивает восстановление прокрутки: 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
Ответ 5
Примечательно, что метод onUpdate={() => window.scrollTo(0, 0)}
устарел.
Вот простое решение для реагирующего маршрутизатора 4+.
const history = createBrowserHistory()
history.listen(_ => {
window.scrollTo(0, 0)
})
<Router history={history}>
Ответ 6
У меня была такая же проблема с моим приложением. Используя нижеприведенный фрагмент кода, я помог мне прокрутить вверх страницы по щелчку следующей кнопки.
<Router onUpdate={() => window.scrollTo(0, 0)} history= {browserHistory}>
...
</Router>
Однако проблема по-прежнему сохраняется в браузере. После многих испытаний выяснилось, что это произошло из-за объекта истории окна браузера, у которого есть свойство scrollRestoration, которое было настроено на auto.Setting this to manual решил мою проблему.
function scrollToTop() {
window.scrollTo(0, 0)
if ('scrollRestoration' in history) {
history.scrollRestoration = 'manual';
}
}
<Router onUpdate= {scrollToTop} history={browserHistory}>
....
</Router>
Ответ 7
Я написал компонент более withScrollToTop
порядка, называемый withScrollToTop
. Этот HOC принимает два флага:
-
onComponentWillMount
- прокручивать ли вверх по навигации (componentWillMount
) -
onComponentDidUpdate
- прокручивать вверх до обновления (componentDidUpdate
). Этот флаг необходим в случаях, когда компонент не размонтирован, но происходит событие навигации, например, от/users/1
to/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);
Ответ 8
Вот еще один метод.
Для response-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()
мы setImmediate()
нашей функции после завершения браузера сброса уровня прокрутки, что дает нам желаемый эффект.
Ответ 9
с React Router 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}/>
надеюсь, что это поможет больше о восстановлении прокрутки
Ответ 10
В компоненте ниже <Router>
Просто добавьте React Hook (если вы не используете класс React)
React.useEffect(() => {
window.scrollTo(0, 0);
}, [props.location]);
Ответ 11
Для небольших приложений с 1-4 маршрутами вы можете попытаться взломать его с помощью перенаправления на верхний элемент DOM с помощью #id, а не просто маршрута. Тогда нет необходимости заключать Routes в ScrollToTop или использовать методы жизненного цикла.
Ответ 12
Я хочу поделиться своим решением для тех, кто использует react-router-dom v5
, поскольку ни одно из этих решений v4 не помогло мне.
Что решило мою проблему, так это установив response-router-scroll-top и поместив обертку следующим образом:
const App = () => (
<Router>
<ScrollToTop>
<App/>
</ScrollToTop>
</Router>
)
и что это! это сработало!
Ответ 13
render() {
window.scrollTo(0, 0)
...
}
Может быть простым решением, если реквизиты не изменены, а componentDidUpdate() не запущен.
Ответ 14
Я обнаружил, что работает ReactDOM.findDomNode(this).scrollIntoView()
. Я разместил его внутри componentDidMount()
.
Ответ 15
Это хаки (но работает): я просто добавляю
window.scrollTo(0,0);
render();