API叩いてReactとサーバーサイドでやり取りしてみる

[Laravel6 x React.js x Material-Ui で環境構築しモダン技術で開発](https://qiita.com/morry_48/items/b1c36d9fa220838e5bc7)

以前の記事で、構築した環境で、一覧表示機能を実装したので、記事を書いてみたいと思います。
Reactからaxiosでリクエスト投げて、LaraveでJSONを返して、そのデータを一覧表の中で表示してみたいと思います。

## React側で、まずデータを受け取るためのstateを定義する
表示したいコンポーネントの中にstateを定義します。
今回の場合は受け取ったデータがarrayのため、初期値も空配列で設定しています。
setPostsはpostsの値を変更する唯一のメソッドです。

```react:Home.js
function Home() {

    const [posts, setPosts] = useState([]);
--------------------------------
```

## Reactからaxiosを使いリクエストを投げる

表示したいコンポーネントからaxiosを使用し、サーバーサイドにリクエストを飛ばします。

```react:Home.js
        axios
            .get('/api/posts')             //リクエストを飛ばすpath
            .then(response => {
                setPosts(response.data);
            })                               //成功した場合、postsを更新する（then）
            .catch(() => {
                console.log('通信に失敗しました');
            });                             //失敗した場合(catch)
```

## Routeで呼び出すアクションを指定
Laravelのroutes/api.phpを開き、下記のコードを記載しcontrollerの、どのアクションを指定するか指定します。

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


## 呼び出したindex()でJSONを返す処理を記載

app/Http/Controllers/api/PostController.phpのindex()にJSONを返す記載

```api.php

<?php

namespace App\Http\Controllers\api;

use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::all();
        return response()->json($posts, 200);  //型をJSONに指定します。
    }
｝

```

## サーバーサイドから、データを確認してみる

DBのデータは下記の通り。

![dbのデータ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/5b8fc6c5-b4f1-9e56-ca94-cfb431518368.png)

こちらのデータがJSON形式でサーバーサイドからresponse.dataとして返ってきて、reactのstateであるpostsを更新することになります。
確認してみます。

```Home.js
        axios
            .get('/api/posts')
            .then(response => {
                setPosts(response.data);
                console.log(response.data);

            })
```

chromeで確認してみます。

![response.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/0df5b9b3-c5af-1543-ceb1-6855b90eedfa.png)

ちゃんとデータとして返ってきている事がわかりますね。
このレスポンスデータの形でstateのpostsが更新されるため、例えばタスク１を表示する場合posts[0].name
で取得できるということです。

## 表示するデータを含む配列を作ってJSXの中で使用し、表示


```js:Home.js
    let rows = [];
    posts.map((rowData) =>
        rows.push({
            user_name: rowData.name,
            post: rowData.content,
            btn: <Button color="secondary" variant="contained" key={rowData.id} href={`/post/edit/${rowData.id}`}>編集</Button>,
            deleteBtn: <Button color="primary" variant="contained" href="/" onClick={() => deletePost(rowData)}>完了</Button>
        })
    );

    return(
        <TableBody>
        {rows.map((row, index) => (
            <TableRow key={index}>
                {Object.keys(row).map(function (key, index) {
                    return (
                        <TableCell align="center" key={index}>{row[key]}</TableCell>
                            );
                        })}
                </TableRow>
        <TableBody>
    );
```


画面を確認しましょう。

![index.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378609/f2249074-cf4f-09fb-50a8-10945c0106f1.png)

きちんと表示されていることが確認できました。


## リクエストを投げるタイミングを最初にページにアクセスしたときのみに変更する。

今の状態でも表示はできていますが、繰り返しaxiosのリクエストが走ってしまう設定担っています。
useeffectを使用することで、ページにアクセスしたときのみ、リクエストを送ることができます。

axiosを投げる処理を関数化しuseEffect()の中で呼び出します。
第二引数を空配列に指定することで、空配列が渡ってきたときのみ実行することができます。


```Home.js
    useEffect(() => {
        getPostsData();
    },[])

    function getPostsData(){
        axios
            .get('/api/posts')
            .then(response => {
                setPosts(response.data);
            })
            .catch(() => {
                console.log('通信に失敗しました');
            });
    }
```

今回の記事は以上です。