WEBOPIXEL

Laravelで部分的にReactを使う方法

Posted: 2019.05.08 / Category: PHP / Tag: ,

Laravelアプリケーションで完全なSPAじゃなくて部分的にReactを使ってみたいと思います。

Sponsored Link

Vue.jsからReactに切り替える

LaravelのデフォルトのJSフレームワークはVueですが、簡単にReactに切り替えることができます。
新規プロジェクトを作成したらartisan preset reactコマンドを実行するだけです。

$ composer create-project laravel/laravel laravel-react
$ cd laravel-react
$ php artisan preset react

切り替えたらnpmインストールします。

$ npm install

これでReactを使用する準備が整いました。
下記コマンドでJSファイルの保存を監視&ビルドして進めます。

$ npm watch

コンポーネントの切り替え

Webルーティングでページ毎に別のReactコンポーネントを表示してみます。

TaskProjectの2つのコンポーネントファイルを作成します。

resources/js/components/Task.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

export default class Task extends Component {
	render() {
		return (
			<div>
				<p>タスク</p>
			</div>
		);
	}
}

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

Projectコンポーネントも同じように作成してください。
次に、app.jsで作成したコンポーネントを読み込みます。

resources/js/app.js

require('./components/Task');
require('./components/Project');

これでビュー(html)でidがtaskの場合Taskコンポーネントが表示され、idがprojectの場合はProjectコンポーネントが表示されます。

Laravelのビューファイルを作成し、それぞれのidでdivを配置します。

resources/views/task.blade.php

@extends('layout')
@section('content')
	<h1>タスク</h1>
	<div id="task"></div>
@endsection

resources/views/project.blade.phpも同じように作成してください。 これでそれぞれのページでコンポーネントが読み込まれるようになります。

最後にwebルーティングを設定して、作成したビューファイルが読み込まれるようにします。

routes/web.php

Route::get('/tasks', function () {
	return view('task');
});
Route::get('/projects', function () {
	return view('project');
});

Laravelのデータを表示する

ReactコンポーネントでLaravelのデータを表示してみます。

例えばこんなモデルがあるとします。

app/Models/Task.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
	protected $fillable = [
		'title'
	];
}

コントローラーはApiディレクトリを作成してその中に入れます。

app/Http/Controllers/Api/TaskController.php

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use App\Models\Task;
use App\Http\Controllers\Controller;

class TaskController extends Controller
{
	public function index()
	{
		return Task::all();
	}
}

Reactからアクセスするルーティングはroutes/api.phpに書きます。

routes/api.php

Route::get('/tasks', 'Api\TaskController@index');

これでapi/tasksで一覧がjsonで取得できるようになります。

Taskコンポーネントを下記のようにすれべ、データの取得表示をできるようになります。

resources/js/components/Task.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from "axios";

export default class Task extends Component {
	constructor() {
		super();
		this.state = {
			tasks: []
		};
	}
	componentDidMount() {
		axios
			.get('/api/tasks')
			.then(response => {
				this.setState({
					tasks: response.data
				});

			}).catch(error => {
				console.log(error);
			});
	}
	render() {
		const list = this.state.tasks.map((item) => {
			return <li key={item.id}>{item.title}</li>;
		});
		return (
			<div>
				<ul className="task-list">
					{list}
				</ul>
			</div>
		);
	}
}

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

ログイン時のみデータを取得

今の所APIには誰でもアクセスできますが、ログインしたユーザーだけ見られるようにしましょう。
make:authで通常のLaravelのユーザー登録&ログイン機能を使えるようにします。

$ php artisan make:auth

今回、APIは内部からのアクセスしないのでapiをそのまま置き換えます。
Kernel.php$middlewareGroupsapi部分を下記のように置き換えます。

app/Http/Kernel.php

protected $middlewareGroups = [
	// ....

	'api' => [
		\App\Http\Middleware\EncryptCookies::class,
		\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
		\Illuminate\Session\Middleware\StartSession::class,
		\Illuminate\View\Middleware\ShareErrorsFromSession::class,
		'throttle:60,1',
		'bindings',
	],
];

APIルーターを通常のAuthミドルウェアで囲んで完成です。

routes/api.php

Route::group(['middleware' => 'auth'], function () {
    Route::get('/tasks', 'Api\TaskController@index');
});
LaravelでセッションIDで認証状態をチェックするステートフルなAPIを使う – Qiita

以上、いきなりSPAでリニューアルだ!とかだと難易度高いと思うので、少しづつReactを組み込むみたいなのでもいいのかなと思いました。