はじめに
試しにLaravel+Reactのプロジェクトを作ってみました。
※8/1追記
Docker環境で試してみたので大幅追記しました。
ちなみにReduxやTypeScriptはLaravel環境下でインストールできませんでした💦
こればっかりは別プロジェクトで切り分けて実装してコンパイルしたものを読み込ませるのがよさそうですね。。。
✅環境
Windows/XAMPP/MySQL
✅参考
📚Laravel実践開発
6.8の場合
※8/1追記。
※Docker環境で実施しました。
✅セットアップ~カウンターコンポーネントの作成
laravel/uiをインストール(“1.x”を付けないと最新がインストールされ、Laravelのバージョン6と整合が取れない。)
$ composer require laravel/ui "1.x" --dev $ php artisan ui react --auth React scaffolding installed successfully. $ npm install && npm run dev
webpack.mix.jsが書き換わる。
const mix = require('laravel-mix');
mix.react('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
welcome.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> <!-- Styles --> <link href="{{ asset('css/app.css') }}" rel="stylesheet"> </head> <body> <div id="counter"></div> </body> </html>
js/app.js
require('./bootstrap'); require('./components/Counter');
js/components/Counter.js
import React, {useState} from "react"; import ReactDOM from "react-dom"; const Counter = () => { const [count, setCount] = useState(0); const increment = () => { setCount(count + 1); }; const decrement = () => { setCount(count - 1); }; return ( <> <p>useState Counter:{count}</p> <button onClick={increment}>+</button> <button onClick={decrement}>-</button> </> ); }; ReactDOM.render(<Counter />, document.getElementById("counter"));
※コントローラ周りも後ほど弄ったので若干コード変わってます

✅認証機能+Auth::userを非同期で取得
※div id=”app”はlayouts/app.blade.phpでがっつり使われているのでReactをマウントする際のidに要注意!!
ユーザーテーブル作成
$ php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.12 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.14 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.06 seconds)
※localhost/registerからユーザーデータを作成
ログインデータをReact側(axios)で取得してみる。
HomeController.php
use Illuminate\Support\Facades\Auth; // 認証情報 ~~~~ public function json(){ return Auth::user()->toJson(); }
web.php
Route::get('/json', 'HomeController@json');
http://localhost/jsonにアクセスして確認。

import React, {useState} from "react"; import ReactDOM from "react-dom"; const Counter = () => { const [data, setData] = useState({ id:"none", name:"none" }); const getAction = () => { axios.get("/json") .then(response => { setData(response.data) }) } return ( <> <p>ID:{data.id}</p> <p>User:{data.name}</p> <button onClick={getAction}>get</button> </> ); }; ReactDOM.render(<Counter />, document.getElementById("counter"));

✅User::allの取得
HomeController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User; // Userモデルクラス
use Illuminate\Support\Facades\Auth; // 認証情報
class HomeController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$msg = "Docker × Laravel × React";
$user = Auth::user();
return view('welcome',compact("msg","user"));
}
public function json(){
return User::all()->toJson();
}
}
welcome.blade.php
<div class="card">
<div class="card-header">
{{ $msg }} ログイン:{{ $user->name }}
</div>
<div className="card-body">
<div id="user"></div>
</div>
</div>
User.js
import React, {useState} from "react"; import ReactDOM from "react-dom"; const User = () => { const [data, setData] = useState([]); const getAction = () => { axios.get("/json") .then(response => { setData(response.data) }) } return ( <> {data.map(data => { return ( <p>user{data.id}:{data.name}</p> ) })} <button onClick={getAction}>get</button> </> ); }; ReactDOM.render(<User />, document.getElementById("user"));

せっかくなので入力値を取得できるようにして見る。
web.php
Route::get('/json/{id}', 'HomeController@json');
HomeController.php
public function json($id = 0){ if($id == 0 ){ return User::all()->toJson(); }else{ return User::find($id)->toJson(); } }
User.js
import React, {useState} from "react"; import ReactDOM from "react-dom"; const User = () => { const [users, setUsers] = useState([]); const [user, setUser] = useState({ }); const getAllAction = () => { axios.get("/json") .then(response => { setUsers(response.data) }) } const getSelectAction = () => { let url = document.getElementById("select_num").value; axios.get("/json/"+ url) .then(response => { setUser(response.data) }) } return ( <> <p>ユーザー一覧</p> {users.map(data => { return ( <p>user{data.id}:{data.name}</p> ) })} <button onClick={getAllAction}>取得</button> <p>特定のユーザー</p> {user.id !== 0 && <p>user{user.id}:{user.name}</p> } <div> <input type="number" id="select_num"></input> </div> <button onClick={getSelectAction}>取得</button> </> ); }; ReactDOM.render(<User />, document.getElementById("user"));

備忘録
以下、ホットリロードはDocker上でうまくいかず。mixにするとjsが読み込まれなかった。
※http://localhost/js/app.jsもしくはGoogle Consoleで確認可能
Laravel MixをつかってLaravelのUIをReactで書く
asset(“js/app.js”)だとHMRされない。mix(“js/app.js”)に書き換えてnpm run hot。
✅JSX内での条件分岐
✅Reduxを使う際はどうするのか??※失敗
以下、実装できなかったが、考えてみればLaravel側でDB使っているのであまりRedux使う必要性もないのかなと感じた。
パターン①Docker内でプロジェクト作成するもWebpackが競合して起動できず。。。
var/www# $ mkdir react-pj $ cd react-pj $ npx create-react-app . --typescript $ yarn add axios // Laravelと違いデフォルトでは入っていないため $ yarn start // error The react-scripts package provided by Create React App requires a dependency: "webpack": "4.42.0" Don't try to install it manually: your package manager does it automatically. However, a different version of webpack was detected higher up in the tree: /var/www/node_modules/webpack (version: 4.44.1)
パターン②Reduxだけインストールして使う※Sassと競合する。。。
$ npm i -D redux react-redux $ npm audit fix --force
package.jsonに追記してみる。これまた失敗。
"redux": "^4.0.5", "react-redux": "^7.2.0",
✅TypeScriptを入れてみる※失敗
$ npm i -D typescript @types/node @types/react @types/react-dom npm ERR! File exists: C:\mydev\docker\laravel6.8_react\laravel\node_modules\.bin\sass npm ERR! Remove the existing file and try again, or run npm npm ERR! with --force to overwrite files recklessly.
👆どうやらSassと競合するらしい。。。–forceオプション使っても変わらず。。。
✅CORS問題
ローカル側(異なるポート番号)からためしにAPIを叩いてみるとCORS問題で突破できず。。。
axios.get("http://localhost/json") .then(response => { setUsers(response.data) }) }
Access to XMLHttpRequest at ‘http://localhost/json’ from origin ‘http://localhost:3002’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
npm からの移行 どうやらyarnもnpmも共存はできるっぽい。
余談
※以下記載の5.8と同じ方法でもローカル環境下では問題なく作れました。ですが、Docker環境下ではうまくいかず。。。
5.8の場合
※書籍のバージョンが5.8なのでまずは5.8から構築していこうと思います。
✅Reactを使うまでの環境構築
①プロジェクト生成
composer create-project laravel/laravel laravel-react --prefer-dist "5.8.*"
②デフォルトではVue.jsがセットされているのでReactに変更
※package.jsonが変更される。
php artisan preset react
変更前
"vue": "^2.5.17"
変更後
"@babel/preset-react": "^7.0.0", "react": "^16.2.0", "react-dom": "^16.2.0",
③パッケージのインストール
npm install
④プロジェクトのビルド
npm run dev
✅Reactコンポーネントの表示
①デフォルトで作られているコンポーネントの確認
resources/js/components/Exaple.js
import React, { Component } from "react"; import ReactDOM from "react-dom"; export default class Example extends Component { render() { return ( <div className="container"> <div className="row justify-content-center"> <div className="col-md-8"> <div className="card"> <div className="card-header">Example Component</div> <div className="card-body"> I'm an example component! </div> </div> </div> </div> </div> ); } } if (document.getElementById("example")) { ReactDOM.render(<Example />, document.getElementById("example")); }
app.jsの確認
require('./bootstrap'); require('./components/Example');
webpack.mix.jsの確認
const mix = require('laravel-mix'); mix.react('resources/js/app.js', 'public/js') .sass('resources/sass/app.scss', 'public/css');
🙄コンポーネントがapp.jsで読み込まれて、webpack.mix.jsでコンパイルされているのがわかります。
②resources/views/welcome.blade.phpの編集
※根こそぎ落としました。
<body> <h1>Laravel</h1> <div id="example"></div> <script src="{{asset('/js/app.js')}}"></script> </body>
③起動して確認
php artisan serve
http://127.0.0.1:8000/へアクセスして確認。

✅試しに関数型コンポーネント
Example.jsを編集
import React from "react"; import ReactDOM from "react-dom"; export default function Example(){ return ( <div className="container"> <div className="row justify-content-center"> <div className="col-md-8"> <div className="card"> <div className="card-header">Example Component</div> <div className="card-body"> I'm an example component!※function </div> </div> </div> </div> </div> ); } if (document.getElementById("example")) { ReactDOM.render(<Example />, document.getElementById("example")); }
ビルド
npm run build
起動
php artisan serve
http://127.0.0.1:8000/へアクセスして確認

🙄関数型コンポーネントも問題なしですね!!
おわりに
割と簡単にReactのテンプレートを表示することができました◎
気が向いたら6.8でも試してみようと思いますが、5.8の方が構築が楽そう。
⇒どちらも特に難しさは変わらずでした。
非同期もVue.jsと同じくクリックイベントなりで発火されるaxios込みの関数を使えばできそうですし、できることは同じですね!
どちらのFWを選ぶかは好みになりそう。
👆これでToDoアプリ制作も面白そう。
こんなのもあった。
バージョン6以降ならこれ参考になりそう。laravel/uiを使うらしい。
コメントを残す