【備忘録】React Routingについてまとめてみた。

# React Routing

ReactにおけるRoutingを勉強したのでそのまとめ。
間違ってる箇所あったら教えてください...

### 前提
ReactはSPA(Single Page Application)。
　その特徴として、最初にページをサーバーから持ってくる。あとはjsを使って、中身のレンダリングを行い表示を更新していくことでページの更新を高速化している。
Reactの特徴をうまく使うためには、Routingするためのライブラリをインストールして使う必要あり。

プロジェクトは```npx create-react-app```でセットアップ。

使うLibrary: react-router-dom

ライブラリをインストールして、dependenciesに追加。
```npm install react-router-dom --save
```

### 手順的な

1.インストールした```react-dom```から```BrowserRouter```をインポートして、アプリ全体を囲う(index.js)。


```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')
);
```

2. ```Route```をApp.jsにインポートして、それぞれのページへのルートを設定する。

```
<Route exact path='/' component={SomeComponent}>

exact -> pathと完全一致するものをレンダリング
path -> パスとなるurlの設定。'/'はベースurl
component-> レンダリングしたいコンポーネントを渡す
```

```App.js
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;
```

3. ```Switch```コンポーネントを使い、全てのRouteコンポーネントを囲うことで、より正確なレンダリングができる。
  マッチしたうちの一つのコンポーネントだけレンダリングし、他はしないため。(Routeだけ使って、exactを使わないと二つのコンポーネントをレンダリングしたりする...)

```js
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.これを下に情報をフェッチしてコンポーネントレンダリングできたりする。
        }
    }
}
}
```
```js
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
```js
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作れたりする)

```js

const Button = (props) => {
  return <button onClick={() => props.history.push('/topics')}>button</button>;
};

function App() {
  return (
    <div>
      <Button />
    </div>
  );
}

export default App;
```

### Linkコンポーネントを使って動的にurl作る

```js
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の勉強中です。

[Complete React Developer in 2022 (w/ Redux, Hooks, GraphQL)](https://www.udemy.com/course/complete-react-developer-zero-to-mastery/)