[簡単]React x LaravelのSPAで作るチュートリアル①(環境構築編)

# SPAで作るタスク管理アプリのチュートリアル
勉強会に参加したりするとReact.jsとかVue.jsやってみたくて勉強はしてるけど、`Laravel`とか`Rails`と、どうつなぎ込んでいいか分からんって人が多いみたいやな。

転職用のポートフォリオでもSPA化すると評価は上がるらしいな。知らんけど。

独立した技術として本とかUdemyで触ったりしてるけど、SPA化するような本とか記事は少ないみたいやから困ってる人もいるみたいやね。

かく言う私も初めてSPAのプロジェクトに参加したときは、なんのこっちゃ分かれへんかったけど、自分でタスク管理アプリ作って`JSON`で繋ぎこむ部分が理解出来たら、あとはフロントとバックエンドは別世界で考えられるからちょっとワカル状態なんやな。

予定では

>
①環境構築(Docker/Laravel/React.js/Material-UI)
②[React側でルーティング設定](https://qiita.com/morry_48/items/b9287bbd4a7d4d312c65)
③[Reactで一覧テーブル作成](https://qiita.com/morry_48/items/d0ee66eda70020c3f266)
④[seederで作ったDBのデータをReactに渡して一覧に表示](https://qiita.com/morry_48/items/1f7e7d74eee666e58379)
⑤[新規登録機能](https://qiita.com/morry_48/items/5b2d80b620b3623a4e33)
⑥[編集・削除機能](https://qiita.com/morry_48/items/261becf645a76eec13cf)

みたいな感じで進めていくつもりや
Laravelに関してはJSON返すだけやから、普段Railsの人がこのチュートリアルやってみたら、
Railsに置き換えることは簡単やと思うわ。

React.jsとVue.jsの違いは語れるほど理解できてないから何も言わんとくわな。

下のGIFみたいな感じで作っていくで。
転職用のポートフォリオ考えてる人とかはこのチュートリアルやってから、
自分のアプリ作っていったらええんちゃうかな。

[![Image from Gyazo](https://i.gyazo.com/a668cb1e8ca54c904739f836aec029ba.gif)](https://gyazo.com/a668cb1e8ca54c904739f836aec029ba)

## 前提
### Gitをインストール
https://git-scm.com
Mac GitHub SSH接続設定をしておく
### Dockerを使えるようにインストール
https://www.docker.com/products/docker-desktop
[注意]npmやyarnのインストールで下記のエラーが出たらコンテナ内のリソース配分の問題かもしれんから、
preferencesからCPUとかメモリの割当を増やしてみてほしい

## 各種バージョンについて
バージョンはこんな感じ
- php 　　　v8.0.3
- Laravel 　v8.40.0
- MySQL 　　v8.0
- npm　　　　v6.14.4
- Node.js　　v14.2.0
- React.js 　　v17.0.2
- Material-UI 　v4.11

記事書いた時点ではそれなりにモダンな選定やと思われるな

# Laravelの環境構築
環境構築はこちらの記事を使わせてもらうな。
[【忙しい人向け】カップ麺より早く作るDockerでLaravel開発環境構築] (https://qiita.com/ucan-lab/items/d7752b43a9e89cc16b22)
(@ucan-lab さん)
エイリアスを設定してくれていたりで、かなり使いやすいし、
爆速で構築できる且つ環境一致させるのに最適なので、ぜひ使ってみるとええで。
今回の記事はSPAでバックエンドとフロントエンドでデータのやり取りするところをメインにしたいから、サクッと環境作れるのはマジ神やな。
また@ucan-labさんが解説も詳細に書いてくれているので、dockerに強くなりたい人とかチュートリアル中にわからんコマンドとかあったら読んでみるとええでと思うで。(https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4)

文中に登場する`make`コマンドはエイリアスやから`Makefile`見てもらえば実行内容は分かるようにしてくれてはるわ。

まぁ、dockerは別にええわって人はなれてる環境で構築してくれても大丈夫やわ。
その場合`make`コマンドのところは`Makefile`見て良しなに置き換えてくれな。



## 手順

```php
$ git clone https://github.com/ucan-lab/docker-laravel.git
$ cd docker-laravel
# バージョンを合わせる場合は下記コマンドの前に*バージョン対応を参照
$ make create-project


------------
docker compose exec app php artisan migrate:fresh --seed
Dropped all tables successfully.
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (53.49ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (45.63ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (44.11ms)
Database seeding completed successfully.

// migrationが実行されてsuccessfullyまで走りきればOK!
```

ローカルで既にPortが使われてたりするとエラーが出るからそのへんはええ感じにかぶらんように変えてくれておけやで(例：docker-compose.ymlのportsのpublishedを`3306`→`3307`に変更、webのportsの場合も同様)
### *バージョン対応
* Makefileのまま環境構築すると最新版のLaravelとなるため、バージョンを合わせたい場合は`git clone`したディレクトリ直下のMakefileで下記変更を行ってから`make create-project`を行う

```php
#Makefile ６行目をバージョン指定に変える
-	docker-compose exec app composer create-project --prefer-dist laravel/laravel . # こちらは削除
+	docker-compose exec app composer create-project --prefer-dist "laravel/laravel=8.4" . #こちらに変える


```

### `localhost`にアクセスしLaravelの初期画面が表示されたらOKな

![スクリーンショット 2021-06-10 6.33.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/1d708c16-fe47-3b46-5239-ac9db8e064ea.png)


ホンマにカップ麺食う暇もなかったな
### LGTM１００個ぐらい押したいところやわ。

## DBクライアントを利用する場合
コマンドラインで進められる方はスルーしてもOKな
MySQLが8.0のため[TablePlus](https://tableplus.com/)等を利用する(SeaquelProは8.0非対応のはず)


手順通り行っった場合は以下が接続情報となるわ
Host: `127.0.0.1`
Password:`secret`
Port: `3306`
User: `phper`
Database: `laravel_local`



### レコードはまだ存在しないもののuserテーブルとか出来てるの確認できたらOKやね

![スクリーンショット 2021-06-10 6.35.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/bdc13657-b7d6-8694-111d-0796d92d9ce1.png)


### ここまでできたら変更差分を分かりやすくするためにブランチを切ってコミットしておくとええな

```php
$ git checkout -b taskApp
$ git add .
$ git commit -m "TaskAppInit"
```



# Reactの環境構築

### UIのパッケージをインストールし、Reactの導入
npm関連で手順通りやって`This is probably not a problem with npm. There is likely additional logging output above.`が出る場合はdockerのリソースの問題かもしれないから書いておくな

```php
# npmを使えるようにしておく
$ make npm

# UIパッケージ導入
$ docker-compose exec app composer require laravel/ui

# React.js導入
$ docker-compose exec app php artisan ui react --auth

# 下記の様の出たらOK
React scaffolding installed successfully.
Please run "npm install && npm run dev" to compile your fresh scaffolding.
Authentication scaffolding generated successfully.

```
npmでビルド

```php
$ make npm-install

$ make npm-dev

```

## コマンドにより生成された不要なファイルを削除しておく

### resources/viewsの下はシングルページとするためapp.blade.phpのみとする

- 下記4項目を削除する
    - /auth以下
    - layouts - (app.blade.phpをviews直下に移動させlayoutsディレクトリ自体を削除)
    - home.blade.php
    - welcome.blade.php


```
# 削除後にresources/viewsディレクトリ下は下記のようになっていればOK
resources
  ┗ views
    ┗ app.blade.php (layouts下に出来ていたものをviews下に移動する)
```

### views/app.blade.phpを修正
- 既存のコードに対してid="app"の中身を空っぽにするで

```php
# views/app.blade.php
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    <script src="{{ asset('js/app.js') }}" defer></script>

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div id="app">
    # id="app"の中身を空する変更
    </div>
</body>
</html>

```

### resources/js/components/Example.jsを修正
- id="app"としたため、`getElementById`を下記のように変更
    - `example`→`app`

```Example.js
// 20行目以下を修正
export default Example;

if (document.getElementById('app')) {
    ReactDOM.render(<Example />, document.getElementById('app'));
}
```

### routes/web.phpを修正
- シングルページアプリケーションなのでどんなURLだったとしても/views/app.blade.phpを表示するように設定します。

```web.php

// 既存コードの16行目以下を削除
// Route::get('/', function () {
//     return view('welcome');
// });

// Auth::routes();

// Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');

// 追記
Route::get('{any}', function () {
    return view('app');
})->where('any','.*');

```

- Reactを読み込む準備できたのでビルドする

```php
$ make npm-dev

```

- 画面をリロードして`Example Component`という文字列が表示されたらReactの導入はOK
![スクリーンショット 2021-04-29 16.26.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/43d1f2a9-beb0-6eeb-4580-12e5c7989ee7.png)


これは何が表示されているかというと`resources/js/components/Example.js`の中身が表示されている
laravel側のid="app"にExampleコンポーネントの中身を表示しているんやな

試しに下記変更を加えてみるな

- Example.jp
    - className="card-headerの文字列
        - `Example Component` →　`React導入できたわな？？`


```Example.js

import React from 'react';
import ReactDOM from 'react-dom';

function Example() {
    return (
        <div className="container">
            <div className="row justify-content-center">
                <div className="col-md-8">
                    <div className="card">
                        <div className="card-header">React導入できたわな？？</div>

                        <div className="card-body">I'm an example component!</div>
                    </div>
                </div>
            </div>
        </div>
    );
}

export default Example;

if (document.getElementById('app')) {
    ReactDOM.render(<Example />, document.getElementById('app'));
}

```

ビルド(make yarn-dev)すると下記のように表示されるはずやな

![スクリーンショット 2021-04-29 16.33.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/24cedf55-adf8-3c4e-201d-cb027dc51005.png)


### Reactで修正したのに「あれ、、変わらん」みたいなことあるけど、だいたいビルド忘れてるか、キャッシュリロードできてないかどっちかのはずやわ。


## ここまで来たらコミットしとこうな

```php
$ git add .
$ git commit -m "React導入"
```

# Material-UIを導入

日本語の公式ドキュメントがある
- [MATERIAL-UI](https://material-ui.com/ja)

そもそも何やねんって話なんやけどGoogleが提唱してるマテリアルデザインを実現するためのUIフレームワークで、
手っ取り早く見た目がええ感じになるから使っていくな。
https://qiita.com/nogson/items/804dd3a879f482fb7018

ドキュメント通りに進めればOKやから下記のコマンドで進めていくで

```
# コンテナ内でインストール
docker-compose exec web npm install @material-ui/core
```
ボタンをインポートしExample.jsの中で表示してみる

```Example.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Button } from '@material-ui/core'; //Buttonをインポート

function Example() {
    return (
        <div className="container">
            <div className="row justify-content-center">
                <div className="col-md-8">
                    <div className="card">
                        <div className="card-header">React導入できたわな</div>

                        <div className="card-body">Im an example component!</div>
                        //ボタンを追記
                        <Button color="primary" variant="contained">Hello World</Button> 
                    </div>
                </div>
            </div>
        </div>
    );
}

export default Example;

if (document.getElementById('app')) {
    ReactDOM.render(<Example />, document.getElementById('app'));
}


```
ビルド、リロードして`HELLO WORLD`ボタンが表示されたらMaterial-UIの導入はOK
![スクリーンショット 2021-04-29 17.05.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/b9174eb6-b2ba-4619-c4af-1f8afe83741f.png)


ドキュメントがしっかりしているので参考にしながら弄ってみるといいかもしれないな

追加したボタンを以下のように書き換えてみる

```Expamle.js
  <Button color="secondary" variant="contained">ワイがMaterial-UIのボタンやな？？</Button>

```

基本的にインポートしたものはタグ的な感じで使えて
colerとかで簡単に見た目変えたりできるねん。
便利やな。

![スクリーンショット 2021-04-29 17.09.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/354f0706-1e8a-2243-ddca-3b892ea5c88a.png)

マウスオーバーすると色が変わるようになってたり
色々タグやテンプレートがあったりするからイジってみるとええちゃうかな。

### コミットしておくな

```php
git add .
git commit -m "Material-UIの導入"
```

今日はここまでやわ。

### 次回はReactでルーティングの設定
react-router-domというライブラリ使って書きみたいなページ遷移する部分を実装していくで

[![Image from Gyazo](https://i.gyazo.com/b142cfef75680599f3bb9828170fa8cf.gif)](https://gyazo.com/b142cfef75680599f3bb9828170fa8cf)

ほな、LGTMよろしゅーやで。
ソースはGitHubに乗せておくから分からんときはコミット履歴見たら解決できるかもな。
https://github.com/morry48/LaravelReactTaskApp