【History API】SPAにおいてURLが切り替わる仕組み

ReactのSPA(Single Page Application)でURLが切り替わる仕組みには、HTML5のHistory APIが利用されます。

History APIには、pushState()replaceState()popState()などのメソッドがあり、これらを使うことでブラウザの履歴を操作できます。

React Routerなどのルーティングライブラリは、History APIを利用して、ブラウザの履歴を操作し、URLの変更を実現しています。

ReactのSPAでは、画面遷移やコンテンツの切り替えをJavaScriptで行っているため、ブラウザは新たなページをリクエストする必要がありません。

そのため、URLが切り替わってもリクエストは送信されません。

例えば、React Routerを使用している場合、<Link> コンポーネントを使ってページ遷移を行うと、History APIが使われてURLが変更され、新しいコンポーネントが表示されます。

この遷移は、リクエストを送信せずに、JavaScriptだけで完結するので、ページのロード時間を節約することができます。

History APIは、HTML5が導入された2011年に導入されたAPIです。

それ以前のWebページでは、JavaScriptからブラウザの履歴を操作することはできませんでした。

History APIは、ブラウザの履歴を変更するためのpushState()replaceState()メソッドを提供しています。

これらのメソッドを使用することで、JavaScriptからページの履歴を追加したり、変更したりすることができます。

また、popstateイベントを使うことで、履歴を戻ったり進んだりする際に、JavaScript側でイベントを取得することもできます。

History APIは、Ajaxによるコンテンツの動的な読み込みや、SPAのようなJavaScriptによる画面遷移を実現するために重要なAPIです。

SPAにおいては、History APIを使ってURLを変更することで、ユーザがブラウザの「戻る」や「進む」ボタンを使って、遷移履歴を操作できるようになっています。

以下のコードは、ReactアプリケーションでHistory APIを利用してURL履歴をコンソールに表示しています。

// App.js
import React, { useEffect } from 'react';
import { BrowserRouter as Router, Route, Link, useNavigate, useLocation } from 'react-router-dom';

const Home = () => <div>Home</div>;
const About = () => <div>About</div>;
const Contact = () => <div>Contact</div>;

const Navigation = () => {
  const navigate = useNavigate();
  const location = useLocation();

  useEffect(() => {
    console.log('URL has changed to:', location.pathname);

    return () => {
      // Cleanup if necessary
    };
  }, [location]);

  return (
    <nav>
      <ul>
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/about">About</Link>
        </li>
        <li>
          <Link to="/contact">Contact</Link>
        </li>
      </ul>
    </nav>
  );
};

const App = () => {
  return (
    <Router>
      <Navigation />

      <Route path="/" index element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/contact" element={<Contact />} />
    </Router>
  );
};

export default App;

ちなみにreact-router-dom v6 に合わせて書いています。

Navigation コンポーネントで useHistory の代わりに useNavigateuseLocation を使用します。

useEffectlocation の変更を監視して、URL の変更を検出します。