0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React Router とは (v6)

Last updated at Posted at 2024-10-12

react-routerとは

Reactアプリケーションでルーティング(ページ遷移)を実現するためのライブラリです。ルーティングとは、ユーザーが異なるURLにアクセスしたとき、特定のコンポーネントを表示する仕組みのことです。SPAにおいて、React Routerを使うとページ全体を再読み込みすることなく、URLに応じてコンポーネントを切り替えることができます。

基本的な仕組み

BrowserRouter

まず、Routerについて簡単に説明します。Routerは、アプリケーション全体にルーティング機能を提供するコンポーネントです。ルートの履歴管理や、URLの変更に基づいてどのコンポーネントを表示するか決定するために必要です。

BrowserRouterReact Routerのコンポーネントの1つで、Reactアプリケーションにルーティング機能を提供します。Router自体には複数の種類がありますが、最も一般的なのがBrowserRouterです。

主な役割は、アプリケーション全体にルーティングのコンテキストを提供し、アプリが異なるURLにアクセスしたとき対応するコンポーネントを表示することです。 HTMLのWrapperのようなものだと認識しています。

具体的に、HTML5の history API (戻る、進むなどの操作履歴の管理)を利用してURLを管理し、ページの再読み込みなしにナビゲーションを実現します。

また、<Router>の中に別の<Router> レンダリングすることはできません。App.js<BrowserRouter>で囲った場合、それ以上<BrowserRouter>は不要です(※重要)

index.jsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";

import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </StrictMode>
);

Routes

Routesは、複数のルートをグループ化するためのコンポーネントです。URLに応じて表示するルート (path) を決定し、Routeコンポーネントをレンダリングします。

// プロパティの詳細は後ほど記述します
<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/about" element={<About />} />
</Routes>

Route

Routeは、パスに対してどのコンポーネントを表示するか定義するコンポーネントです。RouteはURLパス(path)と表示するコンポーネント(element)を関連付けます。

  <Route path="/" element={<Home />} />

基本的な仕組み まとめ

  1. Router(BrowserRouter) でアプリケーション全体のルーティング機能を有効にします。
  2. Routes でルートのグループを作成し、アプリケーション全体のルートを定義します。
  3. Route で個別のパスに対して対応するコンポーネントを紐づけます。

では実際にルーティングしていきましょう。

react-router-domをインストール

スクリーンショット 2024-10-09 19.12.14.png
codesandboxを使用しています。

$ npm i react-router-dom

以下を作成しました。

./components
    - Home.jsx
    - Page1.jsx
    - Page2.jsx

基本ルーティング

BrowserRouterが基本的なルーティングです。
App.jsxは以下の記述になります。

App.jsx
import "./styles.css";
import { Routes, Route, Link } from "react-router-dom";
import Home from "./components/Home";
import Page1 from "./components/Page1";
import Page2 from "./components/Page2";

export default function App() {
  return (
    <div className="App">
      <Link to="/">HOME</Link>
      <br />
      <Link to="page1">PAGE1</Link>
      <br />
      <Link to="page2">PAGE2</Link>

      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/page1" element={<Page1 />} />
        <Route path="/page2" element={<Page2 />} />
      </Routes>
    </div>
  );
}
Home.jsx
// Page1, Page2も同様に作成します
export default function Home() {
  return (
    <div>
      <h1>HOME</h1>
    </div>
  );
}

これでルーティングされました。
スクリーンショット 2024-10-12 11.15.00.png

Linkコンポーネント , toプロパティ

ページ間のナビゲーションを行うために使用される重要なコンポーネントです。<a>タグのようにURLにリンクを提供しますが、ページの再読み込みを発生させずにクライアントサイドでのルーティングを実現します。SPAの特性を活かし、スムーズなページ遷移ができるのです。

Linkコンポーネントはtoプロパティを使って移動先のURLを指定します。href属性に似ていますが、React Routerではページリロードなしで指定パスに遷移します。

<Link to="/">HOME</Link>
<Link to="page1">PAGE1</Link>

path , element プロパティ

Routeコンポーネントでは、pathelement という2つのプロパティが重要な役割を果たします。pathは、URLパス(ルート)を指定するために使用。

もう1つのelementは、pathに対応するコンポーネントを表示するために使用します。表示したいコンポーネントをJSX形式で渡すのです。通常、HTMLタグやカスタムコンポーネントが設定されます。

<Route path="/about" element={<About />} />

ここまでが基礎的なルーティングです。
他のルーティングも見ていきましょう。

ネストされたページ遷移

Page1を親とし、子ページ Page1DetailsA.jsx と Page1DetailsB.jsx を作成します。

./components
    - Home.jsx
    - Page1.jsx
    - Page1DetailsA
    - Page1DetailsB
    - Page2.jsx
Page1.jsx
import { Link } from "react-router-dom";

export default function Page1() {
  return (
    <div>
      <h1>PAGE1</h1>
      <Link to="/page1/detailsA">Page1DetailsA</Link>
      <br />
      <Link to="/page1/detailsB">Page1DetailsB</Link>
    </div>
  );
}
Page1DetailsA.jsx
import { Link } from "react-router-dom";

export default function Page1DetailsA() {
  return (
    <div>
      <h1>Page1DetailsA</h1>
      <Link to="/page1/detailsA">Page1DetailsA</Link>
      <br />
      <Link to="/page1/detailsB">Page1DetailsB</Link>
    </div>
  );
}

Page1.jsx からコピーして書き換えただけです。 Page1DetailsB.jsx も同じように操作します。

App.jsx
import "./styles.css";
import { Routes, Route, Link } from "react-router-dom";
import Home from "./components/Home";
import Page1 from "./components/Page1";
import Page2 from "./components/Page2";
import Page1DetailsA from "./components/Page1DetailsA"; // 追加
import Page1DetailsB from "./components/Page1DetailsB"; // 追加

export default function App() {
  return (
    <div className="App">
      <Link to="/">HOME</Link>
      <br />
      <Link to="page1">PAGE1</Link>
      <br />
      <Link to="page2">PAGE2</Link>

      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/page1">
          <Route index element={<Page1 />} /> {/*index*/}
          <Route path="/page1/detailsA" element={<Page1DetailsA />} /> {/*追加*/}
          <Route path="/page1/detailsB" element={<Page1DetailsB />} /> {/*追加*/}
        </Route>
        <Route path="/page2" element={<Page2 />} />
      </Routes>
    </div>
  );
}

スクリーンショット 2024-10-12 12.14.05.png

App.js の記述を説明します。まず、ネスト化しているコンポーネントを <Route> で囲う必要があります。

<Route path="/page1">
...
</Route>

Page1のRouteコンポーネントを index 属性に設定します。

<Route index element={<Page1 />} />

indexプロパティ

親ルートにアクセスしたとき、子ルートを指定しない場合に表示される「デフォルトのページ」を定義します。

通常、ルートはpathプロパティでURLを指定しますが、indexを使う場合はpathを指定しません。代わりに、その親ルートが呼び出されたときに表示される「初期コンテンツ」として設定されます。

indexの指定は true , false で使われることがありますが、実際にはindexを指定するだけで「true」と同じ意味になります。index={true} と書く必要はなく、単にindexと書けば、「このルートはインデックスルート」という意味です。

なお、index={false}は基本書きません。indexルートにしたくない場合、そのルートにpathを指定して通常のルートとして扱います。

URLパラメーターを使う

componentsに UrlParameter.jsx を作成します。

UrlParameter.jsx
import { useParams } from "react-router-dom";

export default function UrlParameter() {
  const { id } = useParams();

  return (
    <div>
      <h1>PAGE2</h1>
      <p>URL PARAMETER is {id}</p>
    </div>
  );
}
Page2.jsx
import { Link } from "react-router-dom";

export default function Page2() {
  return (
    <div>
      <h1>PAGE2</h1>
      // パラメータで10を渡す
      <Link to="/page2/10">URL Parameter</Link>
    </div>
  );
}

App.jsx
import "./styles.css";
import { Routes, Route, Link } from "react-router-dom";
import Home from "./components/Home";
import Page1 from "./components/Page1";
import Page2 from "./components/Page2";
import Page1DetailsA from "./components/Page1DetailsA";
import Page1DetailsB from "./components/Page1DetailsB";
import UrlParameter from "./components/UrlParameter"; // 追加

export default function App() {
  return (
    <div className="App">
      <Link to="/">HOME</Link>
      <br />
      <Link to="page1">PAGE1</Link>
      <br />
      <Link to="page2">PAGE2</Link>

      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/page1">
          <Route index element={<Page1 />} />
          <Route path="/page1/detailsA" element={<Page1DetailsA />} />
          <Route path="/page1/detailsB" element={<Page1DetailsB />} />
        </Route>
        <Route path="/page2">
          <Route index element={<Page2 />} /> {/*index*/}
          <Route path=":id" element={<UrlParameter />} /> {/*追加*/}
        </Route>
      </Routes>
    </div>
  );
}

スクリーンショット 2024-10-12 18.40.15.png

useParams

URLに含まれる「動的なパラメータ」にアクセスするため使用されます。ユーザーIDなどを含むURL/users/:idを定義し、そのIDに基づいたユーザー情報を表示したい場合などです。

// const { 値 } と記述する。なんでも可
const { id } = useParams();

// 今回は { id } なので
// コンポーネントで取得する値は :id となる。 
// :値 と記述する
<Route path=":id" element={<UrlParameter />} />

クエリパラメータを使う

components内に QueryParameter.jsx を作成します。

QueryParameter.jsx
import { useSearchParams } from "react-router-dom";

export const QueryParameter = () => {
  const [searchParams, setSearchParams] = useSearchParams();
  // .getにてクエリパラメータに設定した値(name)を取得する。
  const name = searchParams.get("name");
  return (
    <div>
      <h1>QueryParameter</h1>
      <p>Query parameter is {name}</p>
    </div>
  );
};
Page2.jsx
import { Link } from "react-router-dom";

export const Page2 = () => {
  return (
    <div>
      <h1>PAGE2</h1>
      <Link to="/page2/10">UrlParameter</Link>
      <br />
      <Link to="/page2/query?name=hello">QueryParameter</Link> {/*nameに値を設定*/}
    </div>
  );
};
App.jsx
// ...略
import { QueryParameter } from "./components/QueryParameter"; // 追加

export default function App() {
  return (
    <div className="App">
      <Link to="/">HOME</Link>
      <br />
      <Link to="page1">PAGE1</Link>
      <br />
      <Link to="page2">PAGE2</Link>

      <Routes>
        <Route path="/" element={<Home />} />
        {/*page1*/}
        <Route path="/page2">
          <Route index element={<Page2 />} />
          <Route path=":id" element={<UrlParameter />} />
          <Route path="/page2/query" element={<QueryParameter />} /> {/*追加*/}
        </Route>
      </Routes>
    </div>
  );
}

スクリーンショット 2024-10-14 19.21.30.png

useSearchParams

URLのクエリパラメータを取得したり、変更するために使います。

例えば「検索機能」
検索結果の絞り込みやフィルタ条件をURLに含めて保持したいときに便利です。URLに検索条件を含めることで、ページをリロードしても同じ条件で結果が表示されます。

他にも「フィルタリング」
商品一覧pageや記事一覧pageで、カテゴリ・価格帯などのフィルタを設定する際に使います。フィルタ状態をURLに保存することで、ユーザーがリロードしてもそのフィルタ状態を保持できます。

...
// 基礎的な値を取得する
const [searchParams, setSearchParams] = useSearchParams();

  // クエリパラメータ "category" の値を取得する
  const category = searchParams.get("category");

  // クエリパラメータ "page" の値を取得する
  const page = searchParams.get("page");

  const handleCategoryChange = (newCategory) => {
    // クエリパラメータを設定・更新する
    setSearchParams({ category: newCategory, page: "1" }); // 新しいカテゴリを設定し、ページ番号をリセット
  };

  return (
    <div>
      <h1>Current Category: {category}</h1>
      <h2>Current Page: {page}</h2>

      <button onClick={() => handleCategoryChange("electronics")}>
        Show Electronics
      </button>
      <button onClick={() => handleCategoryChange("books")}>
        Show Books
      </button>
    </div>
  );
}

404ページ(Not Found)

404ページ(Not Found)を作るには、存在しないURLへアクセスされたときに表示されるコンポーネントを定義します。そのため、pathプロパティにワイルドカードである*を使用します。*は指定されたルート以外のすべてのURLにマッチするため、存在しないページにアクセスされたときに404ページを表示できます。

App.jsx
import { Routes, Route, Link } from "react-router-dom";
import Home from "./components/Home";
import NotFound from "./NotFound"; // 追加

export default function App() {
  return (
    <div className="App">
      <Link to="/">HOME</Link>

      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="*" element={<NotFound />} /> {/*追加*/}
      </Routes>
    </div>
  );
}

NotFound.jsx
export default function NotFound() {
  return (
    <div>
      <h1>404: Page Not Found</h1>
    </div>
  );
}

スクリーンショット 2024-10-12 10.47.18.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?