[簡単]React x LaravelのSPAで作るチュートリアル④(API取得してReactで一覧表示)

# SPAで作るタスク管理アプリのチュートリアル - seederで作ったDBのデータをAPI取得してReactで一覧表示

今回は第④弾でReactで一覧テーブル作成する部分をやっていくで
>
①[環境構築(Docker/Laravel/React.js/Material-UI)](https://qiita.com/morry_48/items/abd620f051fb4f36dcc2)
②[React側でルーティング設定](https://qiita.com/morry_48/items/b9287bbd4a7d4d312c65)
③[API取得してReactで一覧テーブル作成](https://qiita.com/morry_48/items/d0ee66eda70020c3f266)
④API取得してReactで一覧表示
⑤[新規登録機能](https://qiita.com/morry_48/items/5b2d80b620b3623a4e33)
⑥[編集・削除機能](https://qiita.com/morry_48/items/261becf645a76eec13cf)

### 今回の章から本格的にバックエンドとフロントエンドをAPI連携してデータ取得する部分を実装していくで。

APIの連携の部分だけをやりたい人もおるやろうからこの章のスタート地点としてのブランチを用意しといたから、この章から始める人は`API`っていうブランチがあるから、それを使ってな。

https://github.com/morry48/LaravelReactTaskApp

③章までやってきた人はそのままのブランチで大丈夫やで！

## データ表示のためのDB周りの準備(テーブルとテストデータ作成)

### postsテーブルを作成するためのマイグレーションファイルを作成する

```php
// migrationファイルを作成
$ docker-compose exec app php artisan make:migration create_posts_table --create=posts
```

上記のコマンドを実行すると`_create_posts_table`と名のつくファイルが生成されるのでup()の部分を更新する

```php:_create_posts_table.php
    //ファイルを開くとfunction up()が存在するので書きを記載する
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('content');
            $table->timestamps();
        });
    }
```

### migrateionを実行する

```php
$ docker-compose exec app php artisan migrate                                         
Migrating: 2021_05_03_081009_create_posts_table
Migrated:  2021_05_03_081009_create_posts_table (31.42ms)

```

### migratedされたらDBを確認
DBクライアントで確認する(mysqlコマンドで確認してもOKやで)
![スクリーンショット 2021-05-03 17.24.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/0f19ddde-ea16-5e9b-d3dc-aaa25aca24b1.png)

postsテーブルが生成されて
`id`, `name`, `content`, `create_at`, `updated_at`カラムが生成されていればOKやで。

### postsテーブルのテストデータを作成するためのseederファイルを作成するで

```php
$ docker-compose exec app php artisan make:seeder PostsTableSeeder
Seeder created successfully.

```
上記実行すると`database/seeders/PostsTableSeeder.php`が作成されるので開くと既存コードがあるので
`function run()`に下記を記載する(3レコード分を記載するで)

```php:PostsTableSeeder.php
    public function run()
    {
        //書きを記載する
        \DB::table('posts')->insert([
            [
                'name' => 'モーリー',
                'content' => '肩トレ',
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            ],
            [
                'name' => 'ドンキーコング',
                'content' => 'バナナ食う',
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            ],
            [
                'name' => 'データベース太郎',
                'content' => 'データ投入',
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            ]
        ]);
    }
```

### 記載したら`database/seeders/DatabaseSeeder.php`に実行するための設定をするで

`function run()`に下記を記載する

```php:DatabaseSeeder.php
    public function run()
    {
        $this->call([
            PostsTableSeeder::class,    //追記する
        ]);
    }

```

追記したら、seederを実行するで

```php
//dump-autoload
$ docker-compose exec app composer dump-autoload 

// seedを実行する
$ docker-compose exec app php artisan db:seed
Seeding: Database\Seeders\PostsTableSeeder
Seeded:  Database\Seeders\PostsTableSeeder (28.15ms)
Database seeding completed successfully.

```
### データベース確認する

![スクリーンショット 2021-05-03 18.05.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/cd9f833f-b479-3c53-b43e-bbf874e46140.png)


3レコード分を登録出来ていることを確認。

### 確認出来たらコミットしておこうな

```php
add .
git commit -m "postsテーブル作成とテストデータ投入"
```


## Postのバックエンドを構築する
### mvcに沿ってバックエンドを作っていくな。
この辺が分からん人は個別にLaravelの勉強とかMVCフレームワークをなにか一個やっとくとええと思うわ。
![20190709233353.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/70a50a68-64da-8183-1506-c8ef1d089366.png)

### Postモデルを作成

```php
$ docker-compose exec app php artisan make:model Post
```
今回のプロダクトはメモとしてCRUDするだけやからモデルでロジック的な部分は実装なしやな。
### Postコントローラーを作成
今回はApiでやり取りするから/Apiの下に作る

```php
$ docker-compose exec app php artisan make:controller Api/PostController
```
①コントローラーを作成したら作成したファイルに`index()`を作成する
②(Postモデルをuseしておく)

```php:PostController.php
<?php

namespace App\Http\Controllers\Api;//追記

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Post;  //Postをモデルをuseする

class PostController extends Controller
{
    // postの一覧を表示する
    public function index()
    {
        $posts = Post::all();
        return response()->json($posts, 200);
    }
}
```
`Post::all()`でpostの一覧を取得してJOSNを返す

### ルーティングを記載する
こちらもapiなので、`routes/api.php`

```php:api.php
Route::group(['middleware' => 'api'], function(){
    Route::get('posts', 'App\Http\Controllers\Api\PostController@index');
});

//下記は使わないので削除しておく
//Route::middleware('auth:api')->get('/user', function (Request //$request) {
//    return $request->user();
//});
```
ここまで出来たら
`ルーティング`
`コントローラー`
`モデル`
の流れが出来たからAPIのテストして見るな

## Postmanを使ってAPIテストしてみる

APIの開発現場で、よく使うツールやから使えるようにしといたらええと思うわ。

まぁcurlとかで、確認してもええと思うけど

https://qiita.com/zaburo/items/16ac4189d0d1c35e26d1

### 設定に対して投げるURIを確認する
`artisan route:list`で現在の設定を確認できるで

```
% docker-compose exec app php artisan route:list
+--------+----------+-----------+------+-----------------------------------------------+------------+
| Domain | Method   | URI       | Name | Action                                        | Middleware |
+--------+----------+-----------+------+-----------------------------------------------+------------+
|        | GET|HEAD | api/posts |      | App\Http\Controllers\Api\PostController@index | api        |
|        | GET|HEAD | api/user  |      | Closure                                       | api        |
|        |          |           |      |                                               | auth:api   |
|        | GET|HEAD | {any}     |      | Closure                                       | web        |
+--------+----------+-----------+------+-----------------------------------------------+------------+
```
`App\Http\Controllers\Api\PostController@index`を叩くには
`http://localhost/api/posts`をgetで叩けばいいことが分かるね。

### Postmanで`http://localhost/api/posts`叩く
![スクリーンショット 2021-05-04 0.55.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/dd6e557d-574f-deec-6e7a-a6f6e3b1179e.png)

JSON形式でDBに設定した3レコードがjson形式で返ってきたな。
React側でこのデータを取得すればええことが分かるね。
次のところでやっていくからここまで出来たら
コミットしておこうな

```php
$ git add .
$ git commit -m "laravel側でindex()でpost一覧の取得を実装"
```

## React側でデータを取得する
固定データを表示してる`Home.js`にデータをを表示する部分をやっていくで。

### 既存コードにデータ取得用のコードを追記する

```react:Home.js
import React, { useState, useEffect }　from 'react'; //1行目にuseStateを変更する
import axios from 'axios';　//追記する
```
useStyle();している下に
ステートの定義(posts)とaxiosの定義をする

```react:Home.js
    //定義したスタイルを利用するための設定
    const classes = useStyles();  //既存コードなのでこの下に書く

    //postsの状態を管理する
    const [posts, setPosts] = useState([]);

　　//バックエンドからpostsの一覧を取得する処理
    axios
        .get('/api/posts')
        .then(response => {
            setPosts(response.data);     //バックエンドから返ってきたデータでpostsを更新する
            console.log(response.data);　//取得データ確認用のconsole.log()
        })
        .catch(() => {
            console.log('通信に失敗しました');
        });

    return (
```

ステートとはフロント側で状態を管理するために定義するもの。
初期値としてから配列を定義しておいてバックエンドから返ってきた`response.data`で更新する。

axiosの説明記事
https://qiita.com/ksh-fthr/items/2daaaf3a15c4c11956e9


### ビルドする

```php
$ make npm-dev
```

画面リロードするとデータが取得できている事がわかる。

![スクリーンショット 2021-05-03 18.55.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/7c2afde7-024f-6930-8036-f0706e8da73f.png)

３つデータが取れているが繰り返しリクエストが送られてしまっているため、useEffectを利用して対処する(詳しくは記事参照)

https://qiita.com/morry_48/items/b877e608c2d78954cb10

先程のコードに対して、axiosの処理部分を関数化してuseEffect()の中で呼び出すことで、画面についた際の一回だけリクエストするようにする

```react:Home.js
import React, { useState, useEffect }　from 'react'; //useEffectする

    //画面に到着したらgetPostsDataを呼ぶ
    useEffect(() => {
        getPostsData();
    },[])

    //一覧情報を取得しステートpostsにセットする
    const getPostsData = () => {
        axios
            .get('/api/posts')
            .then(response => {
                setPosts(response.data);
            })
            .catch(() => {
                console.log('通信に失敗しました');
            });
    }
```
### ビルドする

```php
$ make npm-dev
```

![スクリーンショット 2021-05-03 19.03.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/58b19960-9a5a-2bf4-5582-50f125302c60.png)
上記の様に、データが取れたらOK。画面についた時点では空の状態でその後リクエストが投げられてデータが取得出来ていることが分かるね

次はデータを一覧表示するためにrowsにpostsを繋ぎこむで
### その前にコミットしておこうな

```php
$ git add .
$ git commit -m "DBのpostsデータをフロント側で取得しステート(posts)にセット"
```

### バックエンドから取得したデータを一覧表につなぎこむ

```php:Home.js(旧コード)
let rows = [
    {
        name: "モーリー",
        content: "肩トレ",
        editBtn: <Button color="secondary" variant="contained">編集</Button>,
        deleteBtn: <Button color="primary" variant="contained">完了</Button>,
    },{
        name: "ドンキーコング",
        content: "バナナ補給",
        editBtn: <Button color="secondary" variant="contained">編集</Button>,
        deleteBtn: <Button color="primary" variant="contained">完了</Button>,
    },
];

```

getPostDataの下にpostsを整形したデータを入れるrowsを定義する

```php:Home.js(新コード)
    const getPostsData = () => {
        axios
            .get('/api/posts')
            .then(response => {
                setPosts(response.data);
            })
            .catch(() => {
                console.log('通信に失敗しました');
            });
    }

    //空配列として定義する
    let rows = [];
    //postsの要素ごとにrowsで使える形式に変換する
    posts.map((post) =>
        rows.push({
            name: post.name,
            content: post.content,
            editBtn: <Button color="secondary" variant="contained">編集</Button>,
            deleteBtn: <Button color="primary" variant="contained">完了</Button>,
        })
    );
```

ちょっと何してるかわかりにくいかもしれんけど空配列rowsにmap中のpostのデータを整形して配列の要素として追加してるな。

`バックエンド側から取得したデータ(posts)を
フロントエンド側で使う形に整形する変数(rows)に加工し
表示`

という流れはよく使うからマスターしとこうな

### ビルドする

```php
$ make npm-dev
```

### 表示確認
![スクリーンショット 2021-05-03 19.20.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/5a9a18e5-86ce-64bd-74c1-02e37f35df4a.png)

一番下に`データ投入`という行が追加されてたら、実装成功やで

### 纏め
フロントエンドからAPI叩いてデータ取得
データを整形して表示という部分をやっていったな。

### 次の⑤ではデータの新規登録をやっていくで

github乗っけとくわな。
https://github.com/morry48/LaravelReactTaskApp

ほな、LGTMよろしゅーやで