プログラミング

Reactのルーティングについて解説【useHistoryの使い方】

この記事では、ReactによるWebアプリケーションで一番メジャーだと思われる、React Routerを用いてルーティングを扱う方法を説明しています。

この記事を読んで、React Routerについて少しでも理解を深めていただければ幸いです。

本記事の内容

  • 基本的なページ遷移
  • ネストされたページ遷
  • パラメータを扱う
  • その他ページ遷移
  • 404ページを用意する

ルーティングの技術は、SPA(Single Page Application)を作る上では必須の知識となりますので、ぜひこの機会に知識を身につけてください。

0からReactエンジニアになるための手順は、全てここで解説しているので合わせてどうぞ。

Reactロードマップ
【完全無料ロードマップ】Reactエンジニアへなるための方法まとめ【現役Reactエンジニアが解説】Reactを学びたいと思ってますか?Reactエンジニアから勉強方法を学ぶのが一番効率的です。なので今回は、現役のReactエンジニアがReactの学習ロードマップを無料で公開します。Reactは今とても需要が高いスキルなので、今すぐ学びましょう。...

Reactの基本的なページ遷移

まずは、「create-react-app」をして、「react-router-dom」をインストールしてください。

npx create-react-app
npm install react-router-dom

リンクの作り方

まずは、リンクの作り方から説明していきます。

必要な「BrowserRouter」と「Link」を「react-router-dom」からインポートします。

次に、「BrowserRouterタグ」で全体を囲みます。

そして、「Linkコンポーネント」を書いていくのですが、書き方はto=パス名でOK。

今回は「Home」、「Page1」、「Page2」ページを作っていきますので、コードはこんな感じになります。

import './App.css';
import {BrowserRouter, Link, Switch, Route} from "react-router-dom";
import {Routes} from "./components/routing/Routes"

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <Link to="/">Home</Link>
        <br />
        <Link to="/page1">Page1</Link>
        <br />
        <Link to="/page2">Page2</Link>
      </div>
      <Routes />
    </BrowserRouter>
  );
}

export default App;

ルーティング

では、リンクができたので、パスに合わせたコンポーネントを表示させるようにしましょう。

まず、Routeコンポーネントを別ファイルで作ります。(分けなくてもルーティングは作れますが、見やすさのため)

そして、必要な「Switch」と「Route」を「react-router-dom」からインポートします。

次に、全体を「Switchタグ」で囲みます。

最後に、「Routeタグ」を書いていけば完成です。

書き方は、path=パス名でそれぞれ表示させたいコンポーネントを設定するだけです。

コードはこうなります。

import {Switch, Route} from "react-router-dom";

import {Home} from "./Home";
import {Page1} from "./Page1";
import {Page2} from "./Page2";

export const Routes = () => {
  return(
    <>
      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/page1">
          <Page1 />
        </Route>
        <Route path="/page2">
          <Page2 />
        </Route>
      </Switch>
    </>
  );
}

あとは、それぞれ「Home」、「Page1」、「Page2」のコンポーネントを作ってください。
コードは全部こんな感じでOKです。

export const Home = () => {
  return(
    <>
      <h2>Home</h2>
    </>
  );
}

ネストされたページ遷移

では、次にネストされたページを扱っていきます。

今回はpage1配下に「detailA」と「detailB」のページを作ります。

まずは、「Page1コンポーネント」に「DetailA」と「DetailB」へのリンクを追加します。

export const Page1 = () => {
  return(
    <>
      <Link to="/page1/detailA">DetailA</Link>
      <br />
      <Link to="/page1/detailB">DetailB</Link>
      <h2>Page1</h2>
    </>
  );
}

そして、render関数を使って、Routesコンポーネントの中に新しいルーティングの定義を書いていくのですが、書き方としてはRouteの中にさらにSwitchを書いていく感じです。

文字よりもコードを見た方が分かりやすいと思うので、こちらになります。

export const Routes = () => {
  return(
    <>
      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route
          path="/page1"
          render={({match: {url}}) => (
            <Switch>
              <Route exact path={url}>
                <Page1 />
              </Route>
              <Route path={`${url}/detailA`}>
                <DetailA />
              </Route>
              <Route path={`${url}/detailB`}>
                <DetailB />
              </Route>
            </Switch>
          )}
        />

        <Route path="/page2">
          <Page2 />
        </Route>
      </Switch>
    </>
  );
}

また、render関数は「props」を受け取っているので、このように書けば毎回/page1/hogeと書かなくて良くなります。

ルーティングでパラメータを扱う

ルーティングではUrlパラメータやクエリパラメータなどを扱うことがよくあります。

今回は、react-routerを使ったそれらの扱い方を説明していきます。

URLパラメータを扱う

次はURLパラメータを扱っていきます。

URLパラメータを使うことで、/profile/ユーザー名、みたいな良くある感じのURLなどを実装出来ます。

今回は/page2/idの数値と言った感じのURLを実装していきます。

まず、ルーティングの定義を変えます。

書き方は簡単で/page2/:idでOK。

<Route
          path="/page2"
          render={({match: {url}}) => (
            <Switch>
              <Route exact path={url}>
                <Page2 />
              </Route>
              <Route path={`${url}/:id`}>
                <UrlParameter />
              </Route>
            </Switch>
          )}
        />

次に、Page2コンポーネントから/idへのリンクを作ります。

今回は適当なidの配列をループで回して作ります。

export const Page2 = () => {
  const ids = ["0","100","1000"];
  return(
    <>
      {ids.map((id) => (
        <>
          <Link to={`/page2/${id}`}>UrlParameter{id}</Link>
          <br />
        </>
      ))}
      <h2>Page2</h2>
    </>
  );
}

後は、「UrlParameter」というコンポーネントを別ファイルに定義して、URLパラメータを扱えるようにします。

そのためには、「useParams」を「react-router-dom」からインポートします。

そして、それの使い方はこんな感じです。

import {useParams} from "react-router-dom";

export const UrlParameter = () => {
  const {id} = useParams();
  return(
    <>
      <h2>UrlParameter</h2>
      <p>{id}</p>
    </>
  );
}

これでURLに合わせてidが表示されるようになっているかと思います。

クエリパラメータを扱う

次にクエリパラメータの使い方を説明していきます。

クエリパラメータとは、URLの末尾についている?name=hogehogeみたいなもののことです。

例えば、グーグル検索をした時のURLを見てもらうと、そんな感じになっているのが確認できるかと思います。

まずは、Page2コンポーネントにクエリパラメータ用のリンクを作成します。

export const Page2 = () => {
  const ids = ["0","100","1000"];
  return(
    <>
      {ids.map((id) => (
        <>
          <Link to={`/page2/${id}`}>UrlParameter{id}</Link>
          <br />
        </>
      ))}
      <Link to="page2/999?name=hogehoge">Query Parameter</Link>
      <h2>Page2</h2>
    </>
  );
}

次に、リンク先の「UrlParameter」側でクエリパラメータを扱っていきます。

まずは、「react-router-dom」から、「useLocation」をインポートします。

そして、それと「URLSearchParams」といったものを使って、扱いやすい形に変換させます。

後はこれを画面側で表示させるようにすれば完了です。

コードは以下の通り。

import {useParams, useLocation} from "react-router-dom";

export const UrlParameter = () => {
  const {id} = useParams();
  const {search} = useLocation();
  const query = new URLSearchParams(search);
  return(
    <>
      <h2>UrlParameter</h2>
      <p>{id}</p>
      <p>{query.get("name")}</p>
    </>
  );
}

Reactのその他ページ遷移

次に、ページ遷移でstateを渡す方法や、Linkコンポーネントを使わないページ遷移の方法を解説していきます。

Stateを渡すページ遷移

次に、ページ間で「state」のやりとりをする方法を説明していきます。

Reactアプリでは良く使う手法なので、ぜひ覚えておいてください。

やり方は簡単で、Linkコンポーネントの書き方を少し変えるだけです。

今回は「Page1」の「DetailA」ページに「state」を渡します。

書き方は、「state」を設定する書き方にするだけです。

export const Page1 = () => {
  const stateA = "state";
  return(
    <>
      <Link to={{pathname: "/page1/detailA", state: stateA}}>DetailA</Link>
      <br />
      <Link to="/page1/detailB">DetailB</Link>
      <h2>Page1</h2>
    </>
  );
}

次に「DetailAコンポーネント」側で「state」を使えるようにしていきます。

今回は、「useLocation」というものを「react-router-dom」からインポートします。

使い方は超簡単で、以下の通りに書けばOKです。

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

export const DetailA = () => {
  const {state} = useLocation();
  return(
    <>
      <h2>DetailA</h2>
      <p>{state}</p>
    </>
  );

これで、Page2から渡したstateがDetailA側で表示出来ているかと思います。

Linkを使わないページ遷移

次に「Linkコンポーネント」を使わないページ遷移を紹介していきます。

実際のアプリではこういった遷移の方が多いと思うので、これを知っておくの大事です。

今回は、「Page1」に「DetailA」へ遷移するためのボタンを実装します。

これはonClick関数でページ遷移しなければならないので、今までのやり方が使えません。

そこで必要になるのが、「useHistory」です。
使い方は簡単で以下の通りです。

import {Link, useHistory} from "react-router-dom";

export const Page1 = () => {
  const stateA = "state";
  const history = useHistory();

  const onClickButton = () => {
    history.push("/page1/detailA")
  }
  return(
    <>
      <Link to={{pathname: "/page1/detailA", state: stateA}}>DetailA</Link>
      <br />
      <Link to="/page1/detailB">DetailB</Link>
      <h2>Page1</h2>
      <br />
      <button onClick={onClickButton}>Jump to DetailA</button>
    </>
  );
}

「State」を渡したい時は、書き方をこう変えればOKです。

import {Link, useHistory} from "react-router-dom";

export const Page1 = () => {
  const stateA = "state";
  const history = useHistory();

  const onClickButton = () => {
    //history.push("/page1/detailA")
    history.push({
      pathname: "/page1/detailA",
      state: stateA
    })
  }
  return(
    <>
      <Link to={{pathname: "/page1/detailA", state: stateA}}>DetailA</Link>
      <br />
      <Link to="/page1/detailB">DetailB</Link>
      <h2>Page1</h2>
      <br />
      <button onClick={onClickButton}>Jump to DetailA</button>
    </>
  );
}

ページ遷移した後に、きちんと「state」を渡ってきているのがわかるかと思います。

ちなみに、同じように戻るボタンを実装できまして、書き方はこのようになります。

import {useLocation, useHistory} from "react-router-dom";

export const DetailA = () => {
  const history = useHistory();
  const {state} = useLocation();

  const onClickBack = () => {
    history.goBack();
  }
  return(
    <>
      <h2>DetailA</h2>
      <p>{state}</p>
      <button onClick={onClickBack}>back</button>
    </>
  );
}

404ページを用意する

最後に、404ページを実装していきます。

これは、どのページにも一致しないUrlが指定された時に表示するものとなります。

実装の仕方はとても簡単です。

まずは、404ページ用のコンポーネントを用意します。

export const Page404 = () => {
  return(
    <>
      <h2>ページが見つかりません</h2>
    </>
  );
}

後は、このようにルーティングを書けばOKです。

export const Routes = () => {
  return(
    <>
      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route
          path="/page1"
          render={({match: {url}}) => (
            <Switch>
              <Route exact path={url}>
                <Page1 />
              </Route>
              <Route path={`${url}/detailA`}>
                <DetailA />
              </Route>
              <Route path={`${url}/detailB`}>
                <DetailB />
              </Route>
            </Switch>
          )}
        />
        <Route
          path="/page2"
          render={({match: {url}}) => (
            <Switch>
              <Route exact path={url}>
                <Page2 />
              </Route>
              <Route path={`${url}/:id`}>
                <UrlParameter />
              </Route>
            </Switch>
          )}
        />
        <Route path="*">
          <Page404 />
        </Route>
      </Switch>
    </>
  );
}

適当なUrlにしてみると、この404ページが表示されるのが確認できるかと思います。

Reactのルーティングについて解説【useHistoryの使い方】まとめ

今回はReactにおけるルーティングを実装するためのreact-routerを紹介しました。

コードはこちらにもあるので、参考にどうぞ。

https://github.com/hinoharashinya/react-commentary/tree/master/src/components/routing

ルーティングはどのアプリでも使われている基本的な技術なので、復習してきちんと使えるようにしておきましょう。

僕のブログでは他にもプログラミングのことについて色々と記事を書いているので、良ければ見てみてください。

Reactエンジニアになりたい人はこちらからどうぞ

Reactロードマップ
【完全無料ロードマップ】Reactエンジニアへなるための方法まとめ【現役Reactエンジニアが解説】Reactを学びたいと思ってますか?Reactエンジニアから勉強方法を学ぶのが一番効率的です。なので今回は、現役のReactエンジニアがReactの学習ロードマップを無料で公開します。Reactは今とても需要が高いスキルなので、今すぐ学びましょう。...

おわり

ABOUT ME
ひのしん
【執筆者情報】ひのしんです。「正しい努力をすれば誰でも成果は出せる」 をモットーに発信しています。元ニートの現フリーランスエンジニアです。 プログラミング歴は4年ほどで、TOEIC885点を取得。科学と実体験を元にした効率的で正しいスキルアップ(プログラミング・英語・ブログ)の方法を発信してます。
\\こちらの記事が大好評です//