ReactとLaravelをAPI連携する方法

# 作成したサンプル
今回は、ログイン画面で①ユーザ名と②パスワードを入力して、ブラウザのコンソールにサーバから取得したメッセージなどを表示するAPIです。

## 手順
<b>ログイン画面を起動する</b>
![ログイン画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1169664/63641af9-b37e-09c3-a967-2bd834eee42a.png)

<b>ログイン画面で①ユーザ名と②パスワードを入力する。</b>
![ログイン画面2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1169664/9b8dd396-4733-9895-4a51-87de92af3a4b.png)

<b>ブラウザコンソールにで①ユーザ名と②パスワード、③メッセージが返却される</b>
![ログイン画面3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1169664/fdd98586-5072-c263-9069-868fcd51db02.png)


# ディレクトリ構造
frontendフォルダにReactプロジェクトろbackendフォルダには、Laravelプロジェクトを入れます。
```
.
└── ReactLaravelProject/
    ├── backend/
    │   ├── app/
    │   │   └── Http/
    │   │       └── controllers/
    │   │           └── RegisterController.php
    │   └── routes/
    │       └── api.php
    └── frontend/
        ├── public
        ├── src/
        │   ├── App.tsx
        │   └── index.css
        └── tailwind.congif.js    
        
```

# Laravelプロジェクト作成手順
composerコマンドで作成します。
```
composer create-project laravel/laravel backend
```
下記のphpコマンドで「`http://localhost:8000`」にアクセスして起動出来たら完了です。
```
php artisan serve
```

# Reactプロジェクト作成手順
:::note info
<b>(お知らせ)</b>
2025年1月8日時点で、最新のReactバージョンでを作成する際に、
webpackを使った「npx create-react-app (プロジェクト名)」は、非推奨となりました。
Viteなどのビルドツールで作成されることをお勧めします。
:::


## ViteでReactプロジェクトを作成する
下記のコマンドを実行します
```
npm create vite@latest (Reactプロジェクト名)
```

つぎにパッケージをインストールします
```
$ cd (Reactプロジェクト名)
$ npm install
```

おわったら、Reactプロジェクトを起動しましょう。
```
npm run dev
```
# Tailwindcssをインストールする

ReactプロジェクトにTailwindCSSDをインストールしましょう
```
$ cd (Reactプロジェクト名)
$ npm install -D tailwindcss postcss autoprefixer
$ npx tailwindcss init -p
```

つぎに、tailwind.config.jsを更新します。
```frontend/tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    //設定したい拡張子を入れる
    "./src/**/*.{js,jsx,ts,tsx}"
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}


```

つづいて、index.cssを更新します。
```frondend/src/index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

# Axiosをインストールする
Laravelとのデータ通信するためのツール「`axios`」をインストールしましょう。
https://www.npmjs.com/package/axios

```
$ cd (Reactプロジェクト)
$ npm i axios
```

# ログイン画面を作成する

ReactのフォームからLaravelのコントローラにユーザー名とパスワードを渡すには、以下の手順を実施してください。

<b>手順</b>
■フォームのonSubmitイベントをハンドリングします。
■Reactでフォームを送信する際に、onSubmitイベントを使い、フォームデータを取得してAPIリクエストを送信します。

■axiosを使ったAPIリクエストを設定します
(Laravelのバックエンドにデータを送信するために、axiosを利用します。)

■Laravel側でコントローラを作成してデータを受け取る
■Laravelで適切なルートとコントローラを設定し、データを受け取ります。

以下に具体的なコードを示します。

```frontend/src/App.tsx
import axios from "axios";
import { useState } from "react"

function App() {
  const [userName,setUserName] = useState("");
  const [userPassword,setUserPassword] = useState("");

  const handleSubmit = async(e:React.FormEvent)=>{
    e.preventDefault();
    try{
      const response = await axios.post("http://localhost:8000/api/login",
        {
          userName,
          userPassword
        }
      );
      //サーバからのレスポンス
      console.log(response.data);
    }catch(error){
      console.log("error",error);
    }
  }

  return (
    <div className="flex items-center justify-center min-h-screen">
      <form onSubmit={handleSubmit} className="bg-gray-100 border border-gray-300 px-4 py-5 rounded-lg shadow-md">
        <div className="mb-4">
            <label className="block text-gray-700 text-sm font-bold mb-2">
              ユーザー名
            </label>
            <input 
              type="text" 
              name="userName" 
              id="userName"
              placeholder="ユーザー名"
              value={userName}
              onChange={(e)=>setUserName(e.target.value)}
              className="shadow appearnce-none border rounded w-full py-2 px-3 text-gray-700 leadint-tight focus:outline-none focus:shadow-outline"
            />
        </div>
        <div className="mb-4">
            <label className="block text-gray-700 text-sm font-bold mb-2">
              パスワード
            </label>
            <input 
              type="password" 
              name="userPassword" 
              id="userPassword"
              placeholder="パスワード"
              value={userPassword}
              onChange={(e)=>setUserPassword(e.target.value)}
              className="shadow appearnce-none border rounded w-full py-2 px-3 text-gray-700 leadint-tight focus:outline-none focus:shadow-outline"
            />
        </div>
        <div className="flex items-center justify-between">
            <button type="submit" className="bg-blue-500 text-white font-bold px-4 py-4 rounded-lg">
              ログイン
            </button>
            <a href="#" className="inline-block align-baseline font-bold text-sm hover:text-blue-800">
              パスワードを忘れた方はこちら
            </a>
        </div>        
      </form>
    </div>
  )
}

export default App

```

# サーバ側を作る

コントローラを作成しましょう。

```
php artisan make:controller (コントローラ名)
```

Reactから取得したデータをjson形式で返却します。

```backend/app/Http/Controllers/RegisterController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class RegisterController extends Controller
{
    public function login(Request $request)
    {
        // リクエストデータの確認
        \Log::info('Request data:', $request->all());

        $validatedData = $request->validate([
            'userName'=>'required|string',
            'userPassword'=>'required|string'
        ]);

        //ここでデータの処理
        return response()->json([
            'message'=>'ログイン成功',
            'data'=>$validatedData
        ]);
    }
}

```

## API設定をする

```backend/routes/api.php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\RegisterController;//2025.01.08追加

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

Route::post('/login',[RegisterController::class,'login']);//2025.01.08追加

```

CORS設定: フロントエンド（React）からバックエンド（Laravel）にアクセスする場合、Laravel側でCORSを許可する必要があります。config/cors.phpを確認して、'paths' => ['api/*'], が設定されていることを確認してください。

# トラブルシューティング
## ■サーバ通信できない(HTTPステータス：500)の場合
<b>CORS設定を確認</b>
ReactアプリケーションからLaravelにリクエストを送信する際、CORSの設定が必要です。

cors.phpの設定確認（config/cors.php）
デフォルトでは、APIルートが許可されるよう設定されているはずです：

```
'paths' => ['api/*'],
```

CORSの設定が適切でない場合は、以下を追加してください：
```
'allowed_origins' => ['*'], // または特定のフロントエンドのURL
```

設定変更後、キャッシュをクリアします：
```
php artisan config:cache
```

## Axiosリクエストの問題
axios.postで送信しているデータがLaravelで期待する形式になっているかを確認してください。LaravelはデフォルトでContent-Type: application/json形式のリクエストを処理します。

もしLaravelがリクエストデータを正しく認識しない場合、ヘッダーを明示的に指定してください：
```App.tsx
const response = await axios.post(
  "http://localhost:8000/api/login",
  { userName, userPassword },
  {
    headers: {
      "Content-Type": "application/json",
    },
  }
);

```





# 参考にしたサイト

https://monotein.com/blog/react-vite-how-to-use

https://tailwindcss.com/docs/guides/create-react-app

https://qiita.com/Sicut_study/items/7147e47441557a43b0fe

https://inakademac.com/laravel-react/

https://qiita.com/kensukeX/items/a045c5b4ecec033425d4#%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E5%81%B4

https://github.com/kamijin-fanta/react-boilerplate-2023/tree/master/src/api