【React】遷移する度にページの一番上へスクロールさせる

【React】遷移する度にページの一番上へスクロールさせる

Reactで作成するアプリケーションでは、リンク経由でページ遷移をしても画面が書き換わるだけでページのスクロールポジションまでは初期化されません。

react-routerを利用している場合、ページ遷移をするタイミングで任意の処理を実行できます。この処理を使ったスクロールポジションの初期化方法を解説します。

react-routerのonChangeコールバックを使う(react-router v3以下)

react-routerの onChange コールバックを使います。
onChange コールバックは、ページのパスが書き変わった度に実行されます。

次のコードを見てください。

import React from "react";
import { Route } from "react-router";

import App from "components/App";
import Profile from "components/Profile";

// onChangeに渡すコールバック
const handleLocationChange = (prevState, nextState) => {
  if (nextState.location.action !== "POP") {
    window.scrollTo(0, 0);
  }
};

export default (
  <Provider store={store}>
      <Router history={history}>
         {/* onChange */}
          <Route path="/" component={App} onChange={handleLocationChange}>
            <Route path="profile" component={Profile} />
            ...
          </Route>
      </Router>
  </Provider>
);

ページが進む度に、window.scrollTo(0, 0)を実行するコールバック関数を渡しています。
これは、pathが / 配下のURL全てに適用されます。

その他にも、ページに入った時に実行される onEnter や、ページを抜ける時に実行する onLeave などもあります。

【参考】Scroll to top on route change?

react-router v4の場合

v4の場合はAPIが変わるため、locationの変更でスクロールするためのコンポーネントを定義します。

import { Component } from 'react';
import { withRouter } from 'react-router';

class ScrollToTop extends Component {
  componentDidUpdate(prevProps) {
    if (this.props.location.pathname !== prevProps.location.pathname) {
      window.scrollTo(0, 0);
    }
  }

  render() {
    return this.props.children;
  }
}

export default withRouter(ScrollToTop);

propsから渡ってくる location をみてパスが変わったら window.scrollTo(0, 0) を実行する実装です。

このScrollToTopコンポーネントは props.children を返すのでルートコンポーネントをラップします。

function App() {
  return (
    <Router>
      <ScrollToTop>
        <App />
      </ScrollToTop>
    </Router>
  );
}

【参考】Scroll Restoration

五十川 洋平(Yohei Isokawa)

五十川 洋平(Yohei Isokawa)

フロントエンドエンジニア/面白法人カヤックなどのWeb制作会社に勤務したのち、故郷の新潟に戻り独立。JSフレームワークAngularやFirebase、Google Cloud Platformを使ったWebアプリ開発が得意。Udemyでプログラミング解説の講師や、ドローンを使った映像制作も行っています。

プロフィール