React Router

ページ遷移

// BrowserRouter このコンポーネントで囲った配下でルーティングを有効にする
import { BrowserRouter, Link, Switch, Route } from "react-router-dom";

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

export default function App() {
  return (
    <BrowserRouter>
      <Link to="/">Home</Link>
      <br />
      <Link to="/page1">Page1</Link>
      <br />
      <Link to="/page2">Page2</Link>
      <br />
      <div className="App"></div>
      {/* Switch どのパスの時にどのコンポーネントを表示するか設定する */}
      <Switch>
        {/* Route Routeにマッチしたパス・画面を表示する */}
        {/* exact 完全一致の場合 */}
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/page1">
          <Page1 />
        </Route>
        <Route path="/page2">
          <Page2 />
        </Route>
      </Switch>
    </BrowserRouter>
  );
}

ネストされたページ遷移

// BrowserRouter このコンポーネントで囲った配下でルーティングを有効にする
import { BrowserRouter, Link, Switch, Route } from "react-router-dom";

import { Home } from "./Home";
import { Page1 } from "./Page1";
import { Page1DetailA } from "./Page1DetailA";
import { Page1DetailB } from "./Page1DetailB";
import { Page2 } from "./Page2";
import "./styles.css";

export default function App() {
  return (
    <BrowserRouter>
      <Link to="/">Home</Link>
      <br />
      <Link to="/page1">Page1</Link>
      <br />
      <Link to="/page2">Page2</Link>
      <br />
      <div className="App"></div>
      {/* Switch どのパスの時にどのコンポーネントを表示するか設定する */}
      <Switch>
        {/* Route Routeにマッチしたパス・画面を表示する */}
        {/* exact 完全一致の場合 */}
        <Route exact path="/">
          <Home />
        </Route>
        <Route
          path="/page1"
          // render関数はpropsをデフォルトで受け取っている
          // console.log(props)で中身を確認
          // matchのurlを使用する
          render={({ match: { url }}) => (
            <Switch>
              <Route exact path={url}>
                <Page1 />
              </Route>
              <Route path={`${url}/detailA`}>
                <Page1DetailA />
              </Route>
              <Route path={`${url}/detailB`}>
                <Page1DetailB />
              </Route>
            </Switch>
          )}
        ></Route>
        <Route path="/page2">
          <Page2 />
        </Route>
      </Switch>
    </BrowserRouter>
  );
}

コンポーネントへ切り出し

// BrowserRouter このコンポーネントで囲った配下でルーティングを有効にする
import { BrowserRouter, Link } from "react-router-dom";
import { Router } from "./router/Router";
import "./styles.css";

export default function App() {
  return (
    <BrowserRouter>
      <Link to="/">Home</Link>
      <br />
      <Link to="/page1">Page1</Link>
      <br />
      <Link to="/page2">Page2</Link>
      <br />
      <div className="App"></div>
      <Router />
    </BrowserRouter>
  );
}
import { Switch, Route } from "react-router-dom";
import { Home } from "../Home";
import { Page2 } from "../Page2";
import { page1Routes } from "./Page1Routes";

export const Router = () => {
  return (
    <Switch>
      {/* Route Routeにマッチしたパス・画面を表示する */}
      {/* exact 完全一致の場合 */}
      <Route exact path="/">
        <Home />
      </Route>
      <Route
        path="/page1"
        render={({ match: { url } }) => (
          <Switch>
            {page1Routes.map((route) => (
              <Route
                key={route.path}
                exact={route.exact}
                path={`${url}${route.path}`}
              >
                {route.children}
              </Route>
            ))}
          </Switch>
        )}
      ></Route>
      <Route path="/page2">
        <Page2 />
      </Route>
    </Switch>
  );
};
import { Page1 } from "../Page1";
import { Page1DetailA } from "../Page1DetailA";
import { Page1DetailB } from "../Page1DetailB";

export const page1Routes = [
  {
    path: "/",
    exact: true,
    children: <Page1 />
  },
  {
    path: "/detailA",
    exact: false,
    children: <Page1DetailA />
  },
  {
    path: "/detailB",
    exact: false,
    children: <Page1DetailB />
  }
];

URLパラメータ

import { Page2 } from "../Page2";
import { UrlParameter } from "../UrlParameter";

export const page2Routes = [
  {
    path: "/",
    exact: true,
    children: <Page2 />
  },
  {
    path: "/:id",
    exact: false,
    children: <UrlParameter />
  }
];
import { Switch, Route } from "react-router-dom";
import { Home } from "../Home";
import { page1Routes } from "./Page1Routes";
import { page2Routes } from "./Page2Routes";

export const Router = () => {
  return (
    <Switch>
      {/* Route Routeにマッチしたパス・画面を表示する */}
      {/* exact 完全一致の場合 */}
      <Route exact path="/">
        <Home />
      </Route>
      <Route
        path="/page1"
        render={({ match: { url } }) => (
          <Switch>
            {page1Routes.map((route) => (
              <Route
                key={route.path}
                exact={route.exact}
                path={`${url}${route.path}`}
              >
                {route.children}
              </Route>
            ))}
          </Switch>
        )}
      ></Route>
      <Route
        path="/page2"
        render={({ match: { url } }) => (
          <Switch>
            {page2Routes.map((route) => (
              <Route
                key={route.path}
                exact={route.exact}
                path={`${url}${route.path}`}
              >
                {route.children}
              </Route>
            ))}
          </Switch>
        )}
      />
    </Switch>
  );
};
import { Link } from "react-router-dom";

export const Page2 = () => {
  return (
    <div>
      <h1>Page2ページです</h1>
      <Link to="/page2/999">URL Parameter</Link>
    </div>
  );
};
import { useParams } from "react-router-dom";

export const UrlParameter = () => {
  // useParams Page2Routes.jsxでidを設定しているためidを受け取れる
  const { id } = useParams();

  return (
    <div>
      <h1>UrlParameterページです</h1>
      <p>パラメータは {id} です</p>
    </div>
  );
};

クエリパラメータ

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

export const Page2 = () => {
  return (
    <div>
      <h1>Page2ページです</h1>
      <Link to="/page2/999">URL Parameter</Link>
      <br />
      <Link to="/page2/999?name=hogehoge">Query Parameter</Link>
    </div>
  );
};
import { useLocation, useParams } from "react-router-dom";

export const UrlParameter = () => {
  // useParams Page2Routes.jsxでidを設定しているためidを受け取れる
  const { id } = useParams();
  // useLocation searchにあるクエリパラメータを使用できる
  const { search } = useLocation();
  // URLSearchParams クエリパラメータを便利に扱えるメソッドを提供してくれる
  const query = new URLSearchParams(search);
  console.log(query);

  return (
    <div>
      <h1>UrlParameterページです</h1>
      <p>パラメータは {id} です</p>
      {/* getメソッドでnameを取得する */}
      <p>クエリパラメータは {query.get("name")} です</p>
    </div>
  );
};

stateを渡すページ遷移

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

export const Page1 = () => {
  // この100件の配列をDtailAページへ持っていく
  const arr = [...Array(100).keys()];
  console.log(arr);

  return (
    <div>
      <h1>Page1ページです</h1>
      {/* stateに対してarr変数を渡す */}
      <Link to={{ pathname: "page1/detailA", state: arr }}>DetailA</Link>
      <br />
      <Link to="/page1/detailB">DetailB</Link>
    </div>
  );
};
import { useLocation } from "react-router-dom";

export const Page1DetailA = () => {
  const { state } = useLocation();
  // stateが渡ってきているか確認
  console.log(state);

  return (
    <div>
      <h1>Page1DetailAページです</h1>
    </div>
  );
};

Linkを使わない遷移(js側で画面遷移)

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

export const Page1 = () => {
  const arr = [...Array(100).keys()];

  const history = useHistory();

  // pushメソッドで遷移先のURLを設定
  const onClickDetailA = () => history.push("page1/detailA");

  return (
    <div>
      <h1>Page1ページです</h1>
      <Link to={{ pathname: "page1/detailA", state: arr }}>DetailA</Link>
      <br />
      <Link to="/page1/detailB">DetailB</Link>
      <br />
      <button onClick={onClickDetailA}>DetailA</button>
    </div>
  );
};
import { useHistory, useLocation } from "react-router-dom";

export const Page1DetailA = () => {
  const { state } = useLocation();

  const history = useHistory();

  // goBackメソッドで遷移元へ戻る
  const onClickBack = () => history.goBack();

  return (
    <div>
      <h1>Page1DetailAページです</h1>
      <button onClick={onClickBack}>戻る</button>
    </div>
  );
};

404ページ

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

export const Page404 = () => {
  return (
    <div>
      <h1>ページが見つかりません</h1>
      <Link to="/">TOPに戻る</Link>
    </div>
  );
};
import { Switch, Route } from "react-router-dom";
import { Home } from "../Home";
import { Page404 } from "../Page404";
import { page1Routes } from "./Page1Routes";
import { page2Routes } from "./Page2Routes";

export const Router = () => {
  return (
    <Switch>
      <Route exact path="/">
        <Home />
      </Route>
      <Route
        path="/page1"
        render={({ match: { url } }) => (
          <Switch>
            {page1Routes.map((route) => (
              <Route
                key={route.path}
                exact={route.exact}
                path={`${url}${route.path}`}
              >
                {route.children}
              </Route>
            ))}
          </Switch>
        )}
      ></Route>
      <Route
        path="/page2"
        render={({ match: { url } }) => (
          <Switch>
            {page2Routes.map((route) => (
              <Route
                key={route.path}
                exact={route.exact}
                path={`${url}${route.path}`}
              >
                {route.children}
              </Route>
            ))}
          </Switch>
        )}
      />
      {/* * 全て一致 */}
      <Route path="*">
        <Page404 />
      </Route>
    </Switch>
  );
};