フロントエンド学習記No.6 React入門 routerの復習 + emotionを使ってみる

# はじめに
今回は簡単な日記アプリを作りながらReact RouterとEmotionを学んでいきます。

## Routerを使った画面遷移
![スクリーンショット 2024-02-18 23.31.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301763/c53fbf58-6800-efe7-50f4-0fe2c4d5fc07.png)

画面遷移１つだけですが・・・笑

実際に遷移する様子、ソースコードは以下を参照してください。

https://github.com/rikuya98/React_Practice/blob/main/README.md



## React Routerとは？

https://reactrouter.com/en/main

Reactのアプリケーションでルーティングを管理するライブラリです
複数ページのアプリケーションを作成する際に使用されます。

Linkを定義したり、Pathごとにレンダリングするコンポーネントを指定したり、ページ遷移する際の動作を提供したり様々な機能があります。

機能ありすぎて追いつかなかったので基本となるものだけ使っていきます。

## React Routerのインストール

```
npm install react-router-dom
```
ルートディレクトリでこちらのコマンドを実行
Package.jsonのdependenciesに  react-router-dom　が追加されていればOKです
```
 "dependencies": {
    "@emotion/react": "^11.11.3",
    "@emotion/styled": "^11.11.0",
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "@types/jest": "^27.5.2",
    "@types/node": "^16.18.82",
    "@types/react": "^18.2.56",
    "@types/react-dom": "^18.2.19",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.22.1",
    "react-scripts": "5.0.1",
    "typescript": "^4.9.5",
    "web-vitals": "^2.1.4"
  },
```


## ReactRouterの基本となるコンポーネント
React Routerが提供する機能を使用するためにはimportして必要なコンポーネントを取り出して使用します。
```react
import { BrowserRouter ,Link, Routes, Route } from 'react-router-dom';
```

### BrowserRouter

公式の説明が難しくてあまりわからない・・・
> A <BrowserRouter> stores the current location in the browser's address bar using clean URLs and navigates using the browser's built-in history stack.

ブラウザのアドレスバーにある現在地を保存したり履歴を使いながら操作してるってことなんだろうか。

詳しいことはわかりませんがルートコンポーネントに置くことでルーティング機能を有効してくれるようです。
これがないとRouterが提供する機能を使用できません。

```React
root.render(
  <React.StrictMode>
    <BrowserRouter>
    <App />
    </BrowserRouter>
  </React.StrictMode>
);
```
このようにしてルートとなるコンポーネントを囲むように配置します。

https://reactrouter.com/en/main/router-components/browser-router

### Link

https://reactrouter.com/en/main/components/link

Linkタグを作成することができます。

toプロパティに指定したPathに遷移することができます。
今回はTOPページ、記事作成ページの２つだけなので、このように書きました。
```React
    <div className="App">
      <nav css={navStyle}>
        <Link to="/" css={linkStyle}>TOPページ</Link>
        <Link to="/article" css={linkStyle}>記事作成</Link>
      </nav>
```

宣言的ナビゲーションというようで、aタグとは違いページを全てリロードせずにレンダリングすることができます。

### RoutesとRoute

https://reactrouter.com/en/main/components/routes

この２つを使用してルーティングの設定を書いていきます。
仕組みとしては
Linkタグなどを押下し、URLが変更されたとき、Routesコンポーネント内に定義されたRouteの中から一致するpathを探します。
そうして一致したRouteコンポーネントのelementプロパティ内に指定されたコンポーネントをレンダリングしページ遷移を行います。

```React
    <Routes>
      <Route path="/" element={<Home posts={posts} />} />
      <Route path="/article" element={<ArticleCreation posts={posts} setPosts={setPosts} />} />
    </Routes>
```

propsを渡したい時はelementプロパティ内で通常時と同様に渡すことができます。
```react
element={<ArticleCreation posts={posts} setPosts={setPosts} />
```

###  routerで遷移を実行する流れ
1. BrowserRouterでルーティング機能を有効に
2. RoutesとRouteでルーティングの設定を行う
3. LinkでRouteに対応するPathに遷移する

このような流れで実装できました。
ちなみに記事投稿時に別のページに遷移などしたい場合は
useNavigateというものを使用するようです。
今回は記事を投稿した時にHomeページへ遷移したかったので使用しました。

```react
import { useNavigate } from "react-router-dom";
    const navigate = useNavigate();
    navigate('/', { state: { message: '記事を投稿しました' } });
```
第１引数に渡したPathに遷移します。
第２引数には遷移先で表示したいmessageなど渡すことができます。

まだまだたくさんの機能があるので、このあたりは何かアプリでも作りながら、必要に応じて知っていきたいと思います。

## Emotionとは
CSS-in-JSを提供するライブラリの１つです。
Styleをjavascriptで定義してコンポーネントに適用することができます。

https://emotion.sh/docs/introduction

### 使い方

ライブラリのインストール
```react
npm install @emotion/react @emotion/styled
```
追加されていることを確認
```react
"dependencies": {
    "@emotion/react": "^11.11.3",
    "@emotion/styled": "^11.11.0",
```

ファイルの先頭にコメントを記述
```react
/** @jsxImportSource @emotion/react */
```
これを記載することでEmotionが提供するStyle機能をjsxまたはtsxに適用できるようになります

cssコンポーネントを取り出し
このような書き方をします
```react
import { css } from '@emotion/react';

const 変数名 = css`[cssの定義]`
```
実際に書いたのがこちら
```HomeStyle.ts
import { css } from '@emotion/react';

export const homeTitle = css`
color: #333;
text-align: center;
margin-bottom: 20px;
`

export const container = css`
max-width: 800px;
margin: 40px auto;
padding: 20px;
background: #f9f9f9;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
`
export const title = css`
color: #007BFF;
font-size: 24px;
margin-bottom: 10px;
`

export const content = css`
color: #666;
line-height: 1.6;
`

export const item = css`
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px solid #eee;
`

export const list = css`
list-style-type: none;
padding: 0;
`
```
Styleは別ファイルに切り出し
exportをつけることで

必要な場所で、必要な数だけ読み込んで使用することもできます。

Home.tsxではこのように使用しました。
cssプロパティに読み込んだ変数をセットすることで適用できます。
```Home.tsx
/** @jsxImportSource @emotion/react */
import { Post } from "../App";
import {container,homeTitle, list, item, title, content } from '../styles/HomeStyles';

interface HomeProps {
    posts: Post[];
}

export const Home = (props: HomeProps) =>{
    const {posts} = props;

    return (
        <div css={container}>
            <h1 css={homeTitle}>日記一覧</h1>
            <ul css={list}>
                {posts.map((post) => (
                    <li css={item} key={post.id}>
                        <h2 css={title}>{post.title}</h2>
                        <p css={content}>{post.content}</p>
                    </li>
                ))}
            </ul>
        </div>
    );
  }
```


## まとめ
以上RouterとEmotionの簡単な使い方と使用例でした！
ライブラリや機能が多すぎて理解が追いつかないですね・・
少しずつ複雑な機能等を取り入れたアプリも作成していく中で学んでいく必要がありそうです。