React Routing
ReactにおけるRoutingを勉強したのでそのまとめ。
間違ってる箇所あったら教えてください...
前提
ReactはSPA(Single Page Application)。
その特徴として、最初にページをサーバーから持ってくる。あとはjsを使って、中身のレンダリングを行い表示を更新していくことでページの更新を高速化している。
Reactの特徴をうまく使うためには、Routingするためのライブラリをインストールして使う必要あり。
プロジェクトはnpx create-react-app
でセットアップ。
使うLibrary: react-router-dom
ライブラリをインストールして、dependenciesに追加。
手順的な
1.インストールしたreact-dom
からBrowserRouter
をインポートして、アプリ全体を囲う(index.js)。
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>
document.getElementById('root')
);
-
Route
をApp.jsにインポートして、それぞれのページへのルートを設定する。
<Route exact path='/' component={SomeComponent}>
exact -> pathと完全一致するものをレンダリング
path -> パスとなるurlの設定。'/'はベースurl
component-> レンダリングしたいコンポーネントを渡す
import { Route } from 'react-router-dom';
const Home = () => {
return (
<div>
<h1>HOME PAGE</h1>
</div>
);
};
const PageA = () => {
return (
<div>
<h1>PAGE A</h1>
</div>
);
};
function App() {
return (
<div className='App'>
<Route exact path='/' component={HomePage} />
<Route path='/pageA' component={PageA} />
</div>
);
}
export default App;
-
Switch
コンポーネントを使い、全てのRouteコンポーネントを囲うことで、より正確なレンダリングができる。
マッチしたうちの一つのコンポーネントだけレンダリングし、他はしないため。(Routeだけ使って、exactを使わないと二つのコンポーネントをレンダリングしたりする...)
import { Switch, Route } from 'react-router-dom';
//省略
function App() {
return (
<div className='App'>
<Switch>
<Route exact path='/' component={HomePage} />
<Route path='/pageA' component={PageA} />
</Switch>
</div>
);
}
export default App;
Dynamic Routing
Route
によりレンダリングされる全てのコンポーネントには3つの引数がpropsとして渡される。(history, location,match)
そのpropsをコンソールログするとこんな感じになる。
{
{
"history": {
"length": 22,
"action": "PUSH",
"location": {
"pathname": "/topics/21",
"search": "",
"hash": "",
"key": "vmo1ru"
}
},
"location": {
"pathname": "/topics/21",
"search": "",
"hash": "",
"key": "vmo1ru"
},
"match": {
"path": "/topics/:topicId",
"url": "/topics/21", //マッチしてる部分のみ
"isExact": true, // もしurlが全てマッチしてればtrue
"params": {
"topicId": "21" //dynamic id.これを下に情報をフェッチしてコンポーネントレンダリングできたりする。
}
}
}
}
import { Switch, Route } from 'react-router-dom';
const HomePage = (props) => {
console.log('homepage: ', props);
return (
<div>
<h1>HOME PAGE</h1>
</div>
);
};
const TopicsList = (props) => {
console.log('topicsList: ', props);
return (
<div>
<h1>Topic List Page</h1>
</div>
);
};
const TopicDetail = (props) => {
console.log('Rendering topicDetail...');
console.log('topicDetail: ', props.match.params.topicId);
return (
<div>
<h1>Topic Detail Page: {props.match.params.topicId}</h1>
</div>
);
};
function App() {
return (
<div>
<Route exact path='/' component={HomePage} />
<Route path='/topics' component={TopicsList} />
<Route path='/topics/:topicId' component={TopicDetail} />
</div>
);
}
export default App;
Link Component
import { Route, Link } from 'react-router-dom';
//省略
function App() {
return (
<div>
<Link to='/topics'>Link</Link>
<Route exact path='/' component={HomePage} />
<Route path='/topics' component={TopicsList} />
<Route path='/topics/:topicId' component={TopicDetail} />
</div>
);
}
export default App;
Link と Route の違いは?
Linkコンポーネント: アプリ全体を再レンダリングするようにリダイレクトする。
Routerコンポーネント: URLを借りてアプリにどの部分を再レンダリングすべきか伝える。
他のdynamic routing
History propsを使う
(Linkと同等だが、イベント発生時に動的にurl作れたりする)
const Button = (props) => {
return <button onClick={() => props.history.push('/topics')}>button</button>;
};
function App() {
return (
<div>
<Button />
</div>
);
}
export default App;
Linkコンポーネントを使って動的にurl作る
import { Switch, Route, Link } from 'react-router-dom';
const HomePage = (props) => {
console.log('homepage: ', props);
return (
<div>
<h1>HOME PAGE</h1>
</div>
);
};
const TopicsList = (props) => {
console.log('topicsList: ', props);
return (
<div>
<h1>Topic List Page</h1>
<Link to={`${props.match.url}/13`}>To Topic 13</Link>
<Link to={`${props.match.url}/17`}>To Topic 17</Link>
<Link to={`${props.match.url}/21`}>To Topic 21</Link>
</div>
);
};
const TopicDetail = (props) => {
console.log('topicDetail: ', props);
return (
<div>
<h1>Topic Detail Page : {props.match.params.topicId}</h1>
</div>
);
};
const Button = (props) => {
return <button onClick={() => props.history.push('/topics')}>button</button>;
};
function App() {
return (
<div>
<Button />
<Link to='/topics'>Link</Link>
<Route exact path='/' component={HomePage} />
<Route path='/topics' component={TopicsList} />
<Route path='/topics/:topicId' component={TopicDetail} />
</div>
);
}
export default App;
参考
以下のudemyの動画にてReactの勉強中です。