railsとreactでtodoアプリを作る！（part2）

# 作成するアプリについて
railsとreactを用いたtodoアプリになります。
https://todo-app-rails-react.herokuapp.com/todoes

https://github.com/taiki-nd/todo-app

（part1）

https://qiita.com/taiki-nd/items/aa9d0a03d1950876efab

（part3）

https://qiita.com/taiki-nd/items/14ff0faf685905532e0f

（part4）

https://qiita.com/taiki-nd/items/ccd07c79a2eca0dba716

（part5）

https://qiita.com/taiki-nd/items/b7b9a6a24f0c99458b2a

# 開発環境
* ruby3.0
* rails6.1(rails6以上必須)
* react17.0.2
* vscode

# アプリの作成手順

1. サーバーサイドの実装
    1. アプリの作成
    1. turbolinksの無効化
    1. モデル＆テーブルの作成
    1. 初期データの作成
    1. top#indexの作成
    1. todoes_controllerの作成
    1. ルーティングの設定
    1. application_controllerの設定
    1. application.html.erbに追記(part1でここまで完了済み)
1. フロントサイドの実装
    1. componentsフォルダの作成
    1. リセットcssと共通cssの設定
    1. index.jsxの記述
    1. フロントの実装準備
    1. App.jsの記述
    1. TodoList.jsの記述
    1. NewTodo.jsの記述
    1. EditTodo.jsの記述

早速ですが進めていきましょう！

# アプリ作成
## 2. フロントサイドの実装
### 2.1 componentsフォルダの作成
この章では必要なcomponentsフォルダを作成していきます。
componentsフォルダの作成場所は``app/javascript``内で作成するcomponentsフォルダは以下の通りです。

* App.js
* EditTodo.js
* NewTodo.js
* TodoList.js
* App.css
![スクリーンショット 2021-11-01 12.09.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645779/0323d744-6026-ce1c-3f58-8478f924c608.png)


### 2.2 リセットcssと共通cssの設定
リセットcssに関しては超簡易版です。必要に応じて変更してください。

```css:javascript/components/App.css
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  color: rgb(1, 1, 1);
}

h1 {
  text-align: center;
  margin-top: 30px;
  margin-bottom: 15px;
}

h2 {
  text-align: center;
  margin-top: 30px;
  margin-bottom: 15px;
}

a {
  text-decoration: none;
  color: rgb(1, 1, 1);
}

input:focus {
  outline: 0;
}
```

### 2.3 index.jsxの記述

以下のように記述していきます。

```jsx:app/javascript/packs/index.jsx
import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom';
import { App } from '../components/App'

document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <BrowserRouter>
      <App />
    </BrowserRouter>,    // <App />を<BrowserRouter>で囲むことで、<App />とその子要素でBrowserRouterを使えるようにしている
    document.querySelector('#root'),
    // app/views/top/index.html.erbからid="root"を選択肢そこに<App />を描画している。
  );
});
```

### 2.4 フロントの実装準備
まずですが、以下の準備作業をしていきます。

```jsx:app/javascript/components/App.js
import React from 'react'

export const App = () => {
  return (
    <div>
      App
    </div>
  )
}
```
```jsx:app/javascript/components/EditTodo.js
import React from 'react'

export const EditTodo = () => {
  return (
    <div>
      EditTodo
    </div>
  )
}
```
```jsx:app/javascript/components/NewTodo.js
import React from 'react'

export const NewTodo = () => {
  return (
    <div>
      NewTodo
    </div>
  )
}
```
```jsx:app/javascript/components/TodoList.js
import React from 'react'

export const TodoList = () => {
  return (
    <div>
      TodoList
    </div>
  )
}
```

``http://localhost:3000/todoes``を確認してみましょう。
![スクリーンショット 2021-11-01 12.38.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645779/775e90ed-cc09-402d-8707-70ec7dc2e28f.png)
これまた隠れてますけど``App``と出力されてますね！

``App``と出力される流れを確認します。

```html:app/views/layouts/application.html.erb
<%= javascript_pack_tag 'index' %>
```
ここで以下が呼び出され

```jsx:javascript/packs/index.jsx
document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <BrowserRouter>
      <App />
    </BrowserRouter>,
    document.querySelector('#root'),
  );
});,
```
この記述で、``<App />``を``document.querySelector('#root')``で取得した以下のファイルに描画し

```html:app/views/top/index.html.erb
<div id="root"></div>
```
出力されます。

### 2.5 App.jsの記述
App.jsxでは全てのページに共通するヘッダー部分とルーティングの記述をしていきます。完成形は以下の通りです。

では実装していきましょう！

```jsx:app/javascript/components/App.js
import React from 'react'
import { Link } from 'react-router-dom'
import styled from 'styled-components'
import './App.css'

export const App = () => {
  return (
    <div>
      <div>
        TODO
      </div>
      <ul>
        <li>
          <Link to="/todoes">
            Todoes
          </Link>
        </li>
        <li>
          <Link to="/todoes/new">
            NewTodo
          </Link>
        </li>
      </ul>
    </div>
  )
}
```

:::note warn
以下のインポートを忘れずに...
・　import { Link } from 'react-router-dom'
・　import styled from 'styled-components'
・　import './App.css'
:::

ここにstyleをあてていきます。

```jsx:app/javascript/components/App.js
import React from 'react'
import { Link } from 'react-router-dom'
import styled from 'styled-components'
import './App.css'

export const App = () => {
  return (
    <Header>
      <Title>
        TODO
      </Title>
      <Actions>
        <Action>
          <Link to="/todoes">
            Todoes
          </Link>
        </Action>
        <Action>
          <Link to="/todoes/new">
            NewTodo
          </Link>
        </Action>
      </Actions>
    </Header>
  )
}

const Header = styled.div`
  background: #ccffcc;
  min-height: 8vh;
  display: flex;
  justify-content: space-around;
  align-items: center;
`

const Title = styled.div`
  font-weight: bold;
  font-size: 24px;
  letter-spacing: 4px;
`

const Actions = styled.ul`
  display: flex;
  width: 400px;
  max-width: 40%;
  justify-content: space-around;
  list-style: none;
`

const Action = styled.li`
  font-size: 20px;
  font-weight: bold;
  opacity: 0.7;
  &:hover {
    opacity: 1;
  }
`
```
デザインはお好みでどうぞ！この通りならば以下のようになっていると思います！
![スクリーンショット 2021-11-01 13.14.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645779/5c6dd150-d315-2c5a-1771-775a72f0c92e.png)

続いてルーティングの実装です。

```jsx:app/javascript/components/App.js
import React from 'react'
import { Link, Route, Switch } from 'react-router-dom'
import styled from 'styled-components'
import './App.css'
import { EditTodo } from './EditTodo'
import { NewTodo } from './NewTodo'
import { TodoList } from './TodoList'

export const App = () => {
  return (
    <>
      <Header>
        <Title>
          TODO
        </Title>
        <Actions>
          <Action>
            <Link to="/todoes">
              Todoes
            </Link>
          </Action>
          <Action>
            <Link to="/todoes/new">
              NewTodo
            </Link>
          </Action>
        </Actions>
      </Header>
      <Body>
        <Switch>
          <Route exact path="/todoes" component={TodoList} />
          <Route exact path="/todoes/new" component={NewTodo} />
          <Route path="/todoes/:id/edit" component={EditTodo} />
        </Switch>
      </Body>
    </>
  )
}

const Header = styled.div`
  background: #ccffcc;
  min-height: 8vh;
  display: flex;
  justify-content: space-around;
  align-items: center;
`

const Title = styled.div`
  font-weight: bold;
  font-size: 24px;
  letter-spacing: 4px;
`

const Actions = styled.ul`
  display: flex;
  width: 400px;
  max-width: 40%;
  justify-content: space-around;
  list-style: none;
`

const Action = styled.li`
  font-size: 20px;
  font-weight: bold;
  opacity: 0.7;
  &:hover {
    opacity: 1;
  }
`

const Body = styled.div`
  width: 700px;
  max-width: 85%;
  margin: 20px auto;
`
```

:::note warn
import { Link } from 'react-router-dom'が以下のように編集されてます。
import { Link, Route, Switch } from 'react-router-dom'
:::

:::note warn
・　import { EditTodo } from './EditTodo'
・　import { NewTodo } from './NewTodo'
・　import { TodoList } from './TodoList'
の追記を忘れないようにしてください。
:::

:::note warn
<>
< />
でHeaderタグとBodyタグがかこまれています。
:::

以上でルーティング処理ができているのでTodoes、NewTodoをクリックすると表示が変わるはずです。
![スクリーンショット 2021-11-01 13.35.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645779/5ccbdbfc-3b67-0d47-e092-734a885cb10a.png)
![スクリーンショット 2021-11-01 13.36.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645779/3f1e688c-9d6c-3b6a-18b0-56a35629e593.png)

このパートはここまでとしましょう！