252

別のページに移動するときに問題が発生しました。その位置は前のページのままです。そのため、自動的に一番上にスクロールしません。window.scrollTo(0, 0)また、onChangeルーターで使用しようとしました。私もscrollBehaviorこの問題を修正するために使用しましたが、うまくいきませんでした。これについて何か提案はありますか?

4

32 に答える 32

28

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

于 2017-06-08T14:48:55.517 に答える
18

onUpdate={() => window.scrollTo(0, 0)}メソッドが古くなっていることは注目に値します。

これは、react-router 4+ の簡単なソリューションです。

const history = createBrowserHistory()

history.listen(_ => {
    window.scrollTo(0, 0)  
})

<Router history={history}>
于 2018-10-12T18:07:59.210 に答える
13

React フック 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;
于 2020-04-13T12:47:52.710 に答える
1

私にとっては、すべての画面で機能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")これで、画面で新しいルートに移動すると、一番上に移動します

于 2021-08-05T17:59:11.650 に答える
1

スムーズスクロールオプション付き

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

export default function ScrollToTop() {
  const { pathname } = useLocation();

  useEffect(() => {
    window.scrollTo({
      top: 0,
      left: 0,
      behavior: 'smooth', 
    });
  }, [pathname]);

  return null;
}

...

<Router>
      <ScrollToTop />
     ...
    </Router>
于 2022-01-26T16:24:48.953 に答える
0

で、この関数をオブジェクト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" },
    ]
});
于 2020-03-31T17:18:03.627 に答える
0

ここに別の方法があります。

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()することで、ブラウザがスクロール レベルのリセットを完了した後に関数が実行され、目的の効果が得られます。

于 2018-05-17T15:17:59.907 に答える
-11

これはハッキーです(ただし機能します):追加するだけです

window.scrollTo(0,0);

レンダリングする();

于 2016-12-09T01:46:33.790 に答える