react-router-dom
Reactで、react-router-domを使ったルーティングを行っていきます。
react-router-domのインストール
npm i -S react-router-dom
ルーティング
BrowserRouter, Route, Switchのインポート
ルーターになるコンポーネントを作るファイル内でBrowserRouter、Route、Switchをインポートします。
import { BrowserRouter, Route, Switch } from "react-router-dom";
要素 | 内容 |
---|---|
BrowserRouter要素 | Switch要素をラップする |
Switch要素 | Route要素をラップする(ラップしたRoute要素のpathが上から1つずつ評価されていく) |
Route要素 | パスネームとページを紐付けする指定を行う |
Route要素のプロパティ | 内容 |
---|---|
exact | pathに指定したパス文字列と、location.pathNameが完全一致した場合のみコンポーネントを返す(exact未指定の場合はfalse) |
path | パス文字列 |
component | ページに相当するコンポーネントを指定 |
:key | useParams、useRouteMatchで使用 |
404ページを作る場合のRoute要素
優先順位を一番低くするため、Swith要素内の一番下にpathを書かないで配置します。
(path未指定だと全てのパスネームにマッチしてしまうため)
ルーティングのサンプル
URLによって、ページA~C、404ページを出し分けます。
ルーター
import { BrowserRouter, Route, Switch} from "react-router-dom";
//各ページに相当するコンポーネントをインポート
import PageA from './page/PageA';
import PageB from './page/PageB';
import PageC from './page/PageC';
import PageD from './page/PageD';
import Page404 from './page/Page404';
function App() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" component={PageA} />
<Route exact path="/pageb" component={PageB} />
<Route exact path="/pagec" component={PageC} />
<Route exact path="/paged" component={PageD} />
<Route component={Page404} />
</Switch>
</BrowserRouter>
);
}
export default App;
ページA
import React from 'react'
const PageA = () => {
return (
<p>ページAにいます。</p>
)
}
export default PageA
ページB
import React from 'react'
const PageB = () => {
return (
<p>ページBにいます。</p>
)
}
export default PageB
ページC
import React from 'react'
const PageC = () => {
return (
<p>ページCにいます。</p>
)
}
export default PageC
ページD
import React from 'react'
const PageD = () => {
return (
<p>ページDにいます。</p>
)
}
export default PageD
404ページ
import React from 'react'
const PageA = () => {
return (
<p>ページが見つかりません</p>
)
}
export default PageA
表示確認
ブラウザのURLを変更して表示が切り替わるか確認します。
URL | 表示内容 |
---|---|
http://localhost:3000 | ページAが表示される |
http://localhost:3000/pageb | ページBが表示される |
http://localhost:3000/pagec | ページCが表示される |
http://localhost:3000/paged | ページDが表示される |
http://localhost:3000/適当な文字列 | 404ページが表示される |
※ホスト名は環境によって変更してください
ページ間のリンク
Linkタグでの遷移
Linkのインポート
発リンクするコンポーネントのファイルでLinkをインポートします。
import { Link } from "react-router-dom";
Linkコンポーネントのtoに指定できる形式
- 文字列形式
- オブジェクト形式
文字列形式
<Link to="/pageb">リンクテキスト</Link>
//パラメータを渡す事もできます。
<Link to="/pageb?sort=name">リンクテキスト</Link>
オブジェクト形式
Link要素に指定できるオブジェクトのプロパティ | 内容 |
---|---|
pathname | パスネーム |
search | パラメータ |
hash | ハッシュ |
state | ユーザ定義のデータ |
<Link
to={{
pathname: "/pageb",
search: "?sort=name",
hash: "hash",
state: { key: "value" }
}}
/>
aタグでの遷移
Linkタグは、コンパイル後aタグになるのでaタグで書く事もできます。
内部リンク
//下記のコードはHTMLに変換するとaタグになるので、直接aタグで記述することもできる
<Link to="/pageB" >ページBへ</Link>
//↓と同じ結果になる
<a href="/pabeB">ページBへ</a>
外部サイトへのリンク
外部リンクはaタグで書きます。
<a href="https://qiita.com/" >Qiitaへ</a>
リンクのサンプル
import React from 'react'
//Linkをインポート
import { Link } from "react-router-dom";
const PageA = () => {
return (
<>
<p>ページAにいます。</p>
<p><Link to="/pageb">ページBへ</Link></p>
<p><a href="https://qiita.com/" target="_blank" rel="noreferrer">Qiitaへ</a></p>
</>
)
}
export default PageA
react-router-domのフック
- useHistory
- useLocation
- useParams
- useRouteMatch
useHistory
historyオブジェクトを返します。
historyオブジェクト | |
---|---|
history.push | URL変更 |
history.goBack | 履歴を戻る |
history.location | historyオブジェクトのプロパティからlocationオブジェクトを取得できる |
useLocation
locationオブジェクトを返します。
locationオブジェクト | 内容 |
---|---|
location.pathname | 現在のパス名 |
location.search | 現在のパラメータ |
location.hash | 現在のハッシュ値 |
location.state | ユーザ定義のデータ |
historyとlocationの違い
URL変更時の挙動 | 内容 |
---|---|
history | 常に同じオブジェクト |
location | 新しいオブジェクトが作られる |
useLocation/useHistory | 使い分け |
---|---|
useLocation | レンダリング中にlocationが必要なときに使う |
useHistory | レンダリング中にlocationが必要ないときに使う |
hitstory.pushでの遷移のサンプル
onClickなどのhandleではLinkタグ、aタグが使えないので、history.pushで遷移させます。
history.pushもLinkタグと同じく文字列とオブジェクトでの遷移先の指定ができます。
ルーター
//追加でuseHistoryをimport
import { BrowserRouter, Route, Switch,useHistory} from "react-router-dom";
//各ページに相当するコンポーネントをインポート
import PageA from './page/PageA';
import PageB from './page/PageB';
import PageC from './page/PageC';
import Page404 from './page/Page404';
function App() {
//historyの取得
const history = useHistory();
return (
{ /* BrouserRouterにhistoryを追加 */ },
<BrowserRouter history={history}>
<Switch>
<Route exact path="/" component={PageA} />
<Route exact path="/pageb" component={PageB} />
<Route exact path="/pagec" component={PageC} />
<Route exact path="/paged" component={PageC} />
<Route component={Page404} />
</Switch>
</BrowserRouter>
);
}
export default App;
発リンクするコンポーネント側
import React from 'react'
//追加でuseHistoryをインポート
import { Link,useHistory } from "react-router-dom";
const PageA = () => {
//historyの取得
const history = useHistory();
return (
<>
<p>ページAにいます。</p>
<p><Link to="/pageb">ページBへ</Link></p>
<p
onClick={() => {
history.push("/pagec");
}}
>
ページCへ
</p>
<p><a href="https://qiita.com/" target="_blank" rel="noreferrer">Qiitaへ</a></p>
</>
)
}
export default PageA
locationを指定した情報の表示のサンプル
ページA
Link要素で、オブジェクト形式で情報を付加して、ページDにリンクします。
import React from 'react'
//追加でuseHistoryをインポート
import { Link,useHistory } from "react-router-dom";
const PageA = () => {
//historyの取得
const history = useHistory();
return (
<>
<p>ページAにいます。</p>
<p><Link to="/pageb">ページBへ</Link></p>
<p
onClick={() => {
history.push("/pagec");
}}
>
ページCへ
</p>
<p
onClick={() => {
history.push({
pathname:"/paged",
search: "?sort=aaa",
hash: "#hash",
state: { test: "成功" }
});
}}
>
ページDへ
</p>
<p><a href="https://qiita.com/" target="_blank" rel="noreferrer">Qiitaへ</a></p>
</>
)
}
export default PageA
ページD
渡した情報が表示されます。
import React from 'react'
import { useLocation } from "react-router-dom";
const PageD = () => {
const location = useLocation();
return (
<>
<p>ページDにいます。</p>
{/* locationで情報を表示します。 */}
<p>pathname: {location.pathname}</p>
<p>search: {location.search}</p>
<p>hash: {location.hash}</p>
<p>state.test: {location.state.test}</p>
</>
)
}
export default PageD
useParams
URLのパスの中で動的に変化する部分の値を取得できます。
パラメータによって表示を変更するサンプル
ルーター
ページEへのリンクを追加(パラメータを付与できるようにする)
import { BrowserRouter, Route, Switch,useHistory} from "react-router-dom";
import PageA from './page/PageA';
import PageB from './page/PageB';
import PageC from './page/PageC';
import PageD from './page/PageD';
import PageE from './page/PageE';
import Page404 from './page/Page404';
function App() {
const history = useHistory();
return (
<BrowserRouter history={history}>
<Switch>
<Route exact path="/" component={PageA} />
<Route exact path="/pageb" component={PageB} />
<Route exact path="/pagec" component={PageC} />
<Route exact path="/paged" component={PageD} />
{/* ページEへのリンクを追加(idというパラメータをつける) */}
<Route exact path="/pagee/:id" component={PageE} />
<Route component={Page404} />
</Switch>
</BrowserRouter>
);
}
export default App;
ページA
ページEへのリンク追加
import React from 'react'
import { Link,useHistory } from "react-router-dom";
const PageA = () => {
const history = useHistory();
return (
<>
<p>ページAにいます。</p>
<p><Link to="/pageb">ページBへ</Link></p>
<p
onClick={() => {
history.push("/pagec");
}}
>
ページCへ
</p>
<p
onClick={() => {
history.push({
pathname:"/paged",
search: "?sort=aaa",
hash: "#hash",
state: { test: "成功" }
});
}}
>
ページDへ
</p>
{/* ページEにリンク(パラメータ違いで3つ)*/}
<p><Link to="/pagee/yamada">ページEへ(yamada)</Link></p>
<p><Link to="/pagee/sato">ページEへ(sato)</Link></p>
<p><Link to="/pagee">ページEへ(パラメータなし)</Link></p>
<p><a href="https://qiita.com/" target="_blank" rel="noreferrer">Qiitaへ</a></p>
</>
)
}
export default PageA
ページE
新規作成
import React from 'react'
//useParamをインポート
import { useParams } from "react-router-dom";
const PageE = () => {
//パラメータを取得
const {id} = useParams();
return (
<>
<p>ページEにいます。</p>
{/* 受け取ったパラメータを表示 */}
<p>ID:{id}</p>
</>
)
}
export default PageE
useRouteMatch
パラメータによってコンポーネント単位でレンダリングの制御ができます。
パラメータによってコンポーネントを出し分けるサンプル
ページEを変更します。
import React from 'react'
//useRouteMatchをインポート
import { useRouteMatch } from "react-router-dom";
const PageE = () => {
//条件の指定
const matchYamada = useRouteMatch('/pagee/yamada');
return (
<>
<p>ページEにいます。</p>
{/* パラメータがyamadaのとき表示するコンポーネント */}
{matchYamada ? <p>IDがyamadaなので表示されています</p> : null}
</>
)
}
export default PageE