【React×Typescript】React RouterのHooksを使ってみよう
おつかれさまです🌞
アイドルに課金するために働いているなりたです。
今回は React Router についての記事です。
私は React Router v5 を使っている期間が長く
v6 が出たから使ってみよう!となった際に
useHistory というHookが useNavigate という名前に変わっていたり
微妙にコードの書き方が変わっていたりして戸惑ったことがあります。
ということで、React Router の Hooks の一部を実際動かしつつ
たまにv5とv6を比較しつつ
どんなことができるのかをまとめてみようと思います🏋️
useLocation
URLに関係するアレコレが取得できます。
v5 でも使えます。
location.hash
URLのハッシュの部分を取得します。location.key
React Router が生成するユニークキーです。
ページを遷移すると変わったりします。location.pathname
URL(baseURL以降)を取得します。
ハッシュとクエリは除外されています。location.search
URLのクエリの部分を取得します。location.state
Link や useNavigate の state で設定した値を取得します。
import { Link, useLocation } from "react-router-dom";
const LocationHook = () => {
const location = useLocation();
return (
<table>
<tbody>
<tr>
<td>{"hash : "}</td>
<td>{location.hash}</td>
</tr>
<tr>
<td>{"key : "}</td>
<td>{location.key}</td>
</tr>
<tr>
<td>{"pathname : "}</td>
<td>{location.pathname}</td>
</tr>
<tr>
<td>{"search : "}</td>
<td>{location.search}</td>
</tr>
<tr>
<td>
<Link to={"/location?test=abc#sys21"} state={{ some: "value" }}>
{"state : "}
</Link>
</td>
<td>{JSON.stringify(location.state)}</td>
</tr>
</tbody>
</table>
);
};
export default LocationHook;
上記サンプルコンポーネント LocationHook を {baseURL}/location で表示するようにして、{baseURL}/location にアクセスしてみます。
サンプルコードではテーブル最下行の state : を押下すると /location?test=abc#sys21 へ遷移するように、
そして stateに{ some: "value" } を設定するようにしています。
ということで、このリンクを踏んでみます。
様々な値が取得できました!
ちなみに同じリンクをもう一度押下すると key には別のハッシュ値が表示されました。
v5では…
<Link>で state を指定したい場合の書き方が少し違います。
先ほどと同じような遷移を行いたい場合には以下のようになります。
<Link
to={{
pathname: "/location?test=abc#sys21",
state: { some: "value" },
}}
>
{"state : "}
</Link>
遷移先のURLも含めてパラメータとして渡すような感じです。
ちなみにクエリやハッシュも以下のように独立して書けます。
<Link
to={{
pathname: "/location",
search: "?test=abc",
hash: "#sys21",
state: { some: "value" },
}}
>
{"state : "}
</Link>
useParams
こちらもv5でも使え、URLの文字列を取得することができます。
例えば以下のようなコンポーネントを作成し、App.tsx にてルーティング設定を行います。
Params.tsx
import { useParams } from "react-router-dom";
export let ParamsHookBlank = () => {
return (
<div>
{"IDの指定なし"}
</div>
);
};
export const ParamsHook = () => {
const { id } = useParams();
return (
<div>
{`idは ${id} です!`}
</div>
);
};
App.tsx
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { ParamsHook, ParamsHookBlank } from "./Params";
function App() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path={"/params"}>
<Route index element={<ParamsHookBlank />} />
<Route path={":id"} element={<ParamsHook />} />
</Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
{baseURL}/params へアクセスすると
ParamsHookBlank コンポーネントを表示{baseURL}/params/{:id} へアクセスすると
ParamsHook コンポーネントを表示
というルーティング設定をしました。
この状態でそれぞれのURLにアクセスすると…
{baseURL}/params/{:id} にアクセスした際に {:id} 部分を取得して表示することができました!
v5では…
useParams にどういうパラメータがやって来るのかを教えてあげる必要がありました。
type ParamTypes = {
id: string;
}
export const ParamsHook = () => {
const { id } = useParams<ParamTypes>();
return (
<div>
{`idは ${id} です!`}
</div>
);
};
useNavigate
v5 でいうところの useHistory に当たるものです。
ページの遷移に使用します。
ページの遷移といえば<Link>要素がありますが
こちらは処理の中でページ遷移を行いたい場合に使います。
そして使い方は基本的に useHistory と同じです。
以下のサンプルでは
ボタンを押下すると先ほど紹介した useLocation と同じように
クエリ等を指定したページ遷移を行うようなものになっています。
<Link>と同じように state も指定することができます。
import { useNavigate } from "react-router-dom";
const NavigateHook = () => {
const navigate = useNavigate();
const handleClick = () => {
navigate("/location?from=navigate#abc", { state: { some: "navigate" } });
};
return (
<div>
<button onClick={handleClick}>ページ遷移</button>
</div>
);
};
export default NavigateHook;
v5(useHistory)では…
history.push() に遷移先のURL等を渡します。
import { useHistory } from "react-router-dom";
const HistoryHook = () => {
const history = useHistory();
const handleClick = () => {
history.push("/location?from=navigate#abc", {
some: "navigate",
});
};
return (
<div>
<button onClick={handleClick}>ページ遷移</button>
</div>
);
};
export default HistoryHook;
【おまけ】最終的なルーティング設定
今までのサンプルを表示するためのルーティング設定を最後に見てみました。
v6の方が要素のネストが少なくてなんだかスッキリしていますね😎
v6
import { BrowserRouter, Route, Routes } from "react-router-dom";
import LocationHook from "./Location";
import { ParamsHook, ParamsHookBlank } from "./Params";
import NavigateHook from "./Navigate";
function App() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path={"/location"} element={<LocationHook />} />
<Route path={"/params"}>
<Route index element={<ParamsHookBlank />} />
<Route path={":id"} element={<ParamsHook />} />
</Route>
<Route path={"/navigate"} element={<NavigateHook />} />
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
v5
import { BrowserRouter, Switch, Route } from "react-router-dom";
import LocationHook from "./Location";
import HistoryHook from "./History";
import { ParamsHook, ParamsHookBlank } from "./Params";
function App() {
return (
<div>
<BrowserRouter>
<Switch>
<Route path="/location">
<LocationHook />
</Route>
<Route path="/params">
<ParamsHookBlank />
</Route>
<Route path="/params/:id">
<ParamsHook />
</Route>
<Route path="/history">
<HistoryHook />
</Route>
</Switch>
</BrowserRouter>
</div>
);
}
export default App;
最後に
改めてまとめてみるとv5/v6両方で使えるHookでも微妙にv6でアップデートされていることがあって新発見でした💡
今後もライブラリのアップデートに遭遇したときは注意深くドキュメントを読んでいきたいです!
(こういうドキュメントはほとんど英語なのでいつもすぐ挫折してしまいますが…😂)