異業種からIT企業に転職して半年以上の初心者です![]()
現場配属されて早3か月が経過しました!はやい!
毎月何かをアウトプットしたいという思いから4月より投稿を継続していますが、今月は、新規画面を実装した時に初遭遇したルーティング(React Router)について備忘録としてまとめたいと思います![]()
React Routerとは
SPA(シングルページアプリケーション)において、画面遷移を行うときは一度HTMLを読み込んだ後、部品(Component)を差し替えて画面遷移をしているかのように振舞います。
この画面遷移をルーティングといい、ReactではReact Routerを用いて実現させます。
感覚としては経路を指定してあげるイメージです↓
Aさん:この商品興味があるから画像見たけどやっぱ違ったとき
リンクをクリック→ページB→ページC→ページA
実装編
仕事現場ではReactのバージョンがv5以下、私が自身で試した作業環境はv6です。
バージョンの違いによって書き方が異なるようだったので、2通りの書き方を備忘録として残しておきます。
ディレクトリ構成
src/
├── pages/
│ ├── Top.tsx (トップページ)
│ ├── Mypage.tsx (マイページ)
│ └── Blog.tsx (ブログページ)
└── App.tsx (ルーティング定義)
v5以下
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Top from './pages/top';
import Mypage from './pages/mypage';
export default function App() {
return (
<Router>
<Switch>
{/* exact は完全一致。つけないと、'/' がすべてに前方一致してしまうため必須。 */}
<Route exact path="/" component={Top} />
{/* /mypage/blog も含めるため、ここでは exact はつけず、部分一致させる。*/}
<Route path="/mypage" component={MyPage} />
</Switch>
</Router>
);
}
]import React from 'react';
import { Link } from 'react-router-dom';
export default function Top() {
return (
<div>
<h1>Top Page</h1>
<Link to="/mypage">My Pageへ</Link>
</div>
);
}
import React from 'react';
import { Route, Switch, useRouteMatch, useHistory } from 'react-router-dom';
import Blog from './Blog';
export default function Mypage() {
const { path, url } = useRouteMatch();
const history = useHistory(); // 画面遷移のためのhistoryオブジェクトを取得
// 各ボタンのクリックハンドラー
const onClickBack = () => {
history.push('/');
};
const onClickBlog = () => {
history.push(`${url}/blog`);
};
return (
<div>
<h1>My Page</h1>
<nav>
<button onClick={onClickBack}>戻る</button>
<button onClick={onClickBlog}>ブログを見る</button>
</nav>
<hr />
<Route path={`${path}/blog`} component={Blog} />
</div>
);
}
import React from 'react';
import { useHistory } from 'react-router-dom';
export default function Blog() {
const history = useHistory();
const onClickBack = () => {
history.goBack();
};
return (
<div>
<h2>Blog</h2>
<button onClick={onClickBack}>戻る</button>
</div>
);
}
v6
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { Top } from './pages/Top.tsx';
import { MyPage } from './pages/MyPage.tsx';
import { Blog } from './pages/Blog.tsx';
export const App = () => (
<BrowserRouter>
<div>
<Routes>
<Route path="/" element={<Top />} />
<Route path="/mypage" element={<MyPage />} />
<Route path="/mypage/blog" element={<Blog />} />
</Routes>
</div>
</BrowserRouter>
);
import { Link } from 'react-router-dom';
export const Top = () => {
return (
<div>
<h1>Top Page</h1>
<Link to="/mypage">My Pageへ</Link>
</div>
);
};
import { useNavigate } from 'react-router-dom';
export const MyPage = () => {
const navigate = useNavigate();
const onClickBlog = () => {
navigate('/mypage/blog');
};
const onClickBack = () => {
navigate(-1);
};
return (
<div>
<h1>My Page</h1>
<button onClick={onClickBlog}>Blogを見る</button>
<button onClick={onClickBack}>戻る</button>
</div>
);
};
import { useNavigate } from 'react-router-dom';
export const Blog = () => {
const navigate = useNavigate();
const onClickBack = () => {
navigate(-1);
};
return (
<div>
<h1>Blog</h1>
<button onClick={onClickBack}>My Pageに戻る</button>
</div>
);
};
v5とv6の違い
パスのマッチ順
v5
BrowserRouterの中で<switch>を使用して上から順にパスを判定するため、exactを使用するかを考える必要があります。
上記のv5のApp.tsxを以下のようにexactを付けないで記述すると、Blogページに飛びたいのにMyPageのパスが先にマッチしてしまうので、画面上にMypageとBlogが二重で表示されてしまいます。(これを知らずに少し沼りました。。。)
<Route path="/mypage" component={MyPage} />
<Route path="/mypage/Blog" component={Blog} />
exactはパスを完全一致で検索するため、つけないと部分一致で検索することになる
v6
v6では<switch>が不要となります!
パスを<Routes>で囲み、必ずパスを完全一致でマッチさせるようになったのでexactを付与する必要もなくなりました。
component属性とelement属性
v5:component属性
v6:element属性
component属性ではコンポーネントに値を渡すときはrender属性を使用する必要がありますが、element属性ではその必要がなくなるため、より直感的で簡便に記述することができるそうです。
ページ遷移
//v5の場合
const history = useHistory();
history.push('path名');
history.goBack(); //1ページ前に戻る
history.back(-2); //2ページ前に戻る
//v6の場合
const navigate = useNavigate();
navigate('path名');
navigate(-1); //1ページ前に戻る
v5:useHistory
v6:useNavigate
v5ではuseHistoryを使用してページ遷移を行いますが、v6ではuseNavigateを使用することでページ遷移を行います。
引数に整数を入れることで履歴があれば、その分ページを進んだり戻ったりすることができます。
さいごに
今回、現場で初めて触れたReact Routerについて復習する中でバージョン違いによる記述の違いにまでたどり着くことができました。
バージョンの違いについてはまだまだありそうですが、今回触れたのはここまででしたので機会があれば、もう少し踏み込んでみようと思います!
最後まで閲覧いただきありがとうございました。
何かありましたら、ご指摘いただけますと幸いです。
