ReactのSPAでページ遷移時にスクロール位置が維持される問題とその対処法 初心者エンジニア向け

目次

なぜページ遷移時にスクロール位置が変わらないのか?

通常のHTMLサイトでは、リンクをクリックするとページ全体がリロードされるため、ページの一番上から表示されます。しかし、Reactでは「SPA(シングルページアプリケーション)」の仕組みを使い、ページ全体をリロードせずに画面の一部だけを書き換えるため、スクロール位置がそのまま残るのがデフォルトの挙動になります。

このため、例えば前のページの下の方を見ていた状態で別のページに移動すると、新しいページでもスクロール位置が下のままになってしまうことがあります。

Viteなどの環境要因は関係あるの?

いいえ、Viteは関係ありません。ViteはReactアプリを高速に開発するためのビルドツールなので、このスクロールの挙動には影響しません。同じように、create-react-app を使っても、同じ問題が発生します。

ページ遷移時にスクロールを上部に戻す方法

ページ遷移後に毎回ページの一番上から表示されるようにするためには、以下のような対処方法を使います。

各ページごとにスクロール位置をリセットする

各ページのコンポーネントでuseEffectを使い、ページを開いたときにスクロールを一番上に移動する方法です。

import { useEffect } from "react";

const SomePage = () => {
  useEffect(() => {
    window.scrollTo(0, 0); // 画面を一番上に移動
  }, []);

  return <div>このページのコンテンツ</div>;
};

export default SomePage;

メリット: ページごとに適用できる ✅ デメリット: 毎回 window.scrollTo(0, 0); を書くのが面倒

ScrollToTop コンポーネントを作成して共通適用(おすすめ!)

毎回 window.scrollTo(0, 0); を書くのは手間なので、共通の ScrollToTop コンポーネントを作成し、React Routerを使ってルーティングの上部に配置する方法が便利です。

ScrollToTop.tsx を作成

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

const ScrollToTop = () => {
  const { pathname } = useLocation();

  useEffect(() => {
    window.scrollTo(0, 0); // ページ遷移時に上部へスクロール
  }, [pathname]);

  return null;
};

export default ScrollToTop;

App.tsxScrollToTop を適用

import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import ScrollToTop from "./ScrollToTop";
import Home from "./Home";
import About from "./About";

function App() {
  return (
    <Router>
      <ScrollToTop /> {/* これを追加! */}
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Router>
  );
}

export default App;

メリット: すべてのページで自動適用されるので楽! ✅ デメリット: React Router を使わない場合は適用できない

まとめ

  • この問題はReactのSPAの仕様 で起こる(Viteは関係なし)
  • 解決策として window.scrollTo(0, 0); を使う
  • 簡単な方法: 各ページごとに useEffect でスクロールをリセット
  • おすすめの方法: ScrollToTop コンポーネントを作ってルーティングの上部に配置

これで、ページ遷移時に毎回 一番上から表示 されるようになります! 🚀

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次