React+Laravelのルーティング
LaravelとReactでSPA(single-page application)の疑似的にルーティングを実装する方法を説明します。
SPAを作るので、呼び出すページは基本的に1つです。呼び出したページの中でreact-router-domを使ってURLによってコンポーネントに振り分けていきます。
上記をまとめると動きは下記のようなになっています。
1.Laraveのルーティングで1つのページをレンダリングする。
2.呼び出したページで呼び出されるjsファイルにコンパイル先を設定する。
3.呼び出したjsファイル内で現在のURLでコンポーネントを振り分ける。
1.Laraveのルーティングで1つのページをレンダリングする。
どのURLにアクセスしても1つのページindex.blade.php
がレンダリングされるようにweb.php
でルーティングを設定します。
Route::get('/{any}', function () {
return view('index');
})->where('any', '.*');
/{any}
に合致した時に、index.blade.php
がレンダリングされます。
where('any', '.*')
でany
がすべての文字が0回以上繰り返した文字列つまりすべてのURLでヒットするようになります。
次は、レンダリングされるindex.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">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Laravel</title>
<script src="{{ asset(mix('js/app.js')) }}" defer></script>
</head>
<body>
<div id="index"></div>
</body>
</html>
下記の行でコンパイルされたapp.js
が読み込まれます。
app.js
が「3.呼び出したjsファイル内で現在のURLでコンポーネントを出しわけする。」で実装するjsファイルがコンパイルされるようになります。
<script src="{{ asset(mix('js/app.js')) }}" defer></script>
2.jsファイルをコンパイル先を呼び出されるファイルに設定する。
実装するjsファイルをコンパイルする先を設定します。
mix.js('resources/js/app.js', 'public/js')
上記の記述でresources/js/app.js
をpublic/js/app.js
としてコンパイルできるように設定します
下記コマンドでコンパイルを行います。
npm run dev
上記で設定したresources/js/app.js
内でcomponents/index
を読み込みます。
require('./components/index');
3.呼び出したjsファイル内で現在のURLでコンポーネントを振り分ける
下記ファイルで現在のURLによってレンダリングされるコンポーネントを振り分けます
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route } from 'react-router-dom';
const Index = () => {
<BrowserRouter>
<Route exact path="/users" component={UsersList} />
<Route exact path="/users/:id" component={UsersShow} />
<Route exact path="/users/create" component={UsersCreate} />
<Route exact path="/users/:id/edit" component={UsersEdit} />
</BrowserRouter>
}
if (document.getElementById('index')) {
ReactDOM.render(<Index />, document.getElementById('index'));
}
下記の記述でid='index'の要素があれば、Indexコンポーネントを描画します。
if (document.getElementById('index')) {
ReactDOM.render(<Index />, document.getElementById('index'));
}
下記がIndexコンポーネントの定義です。
それぞれのコンポーネントの役割は下記になります。
-
BrowserRouter
:window.location(≒URL)が変わる度にどのRoute
に振り分ければいいのかを判断します。 - Route:
location.pathName
(≒URL)がpath
に一致した時にcomponentが描画する- exact:location.pathNameが完全一致した時のみヒットするようになります
const Index = () => {
<BrowserRouter>
<Route exact path="/users" component={UsersList} />
<Route exact path="/users/:id" component={UsersShow} />
<Route exact path="/users/create" component={UsersCreate} />
<Route exact path="/users/:id/edit" component={UsersEdit} />
</BrowserRouter>
}
下記を例に説明します。
Route
はexact
と設定されているのでURLが/users
と完全に一致する時のみ、UsersList
コンポーネントを描画します。
<Route exact path="/users" component={UsersList} />
下記の記述でreact-router
のuseParams
を使うとルーティングパラメータ:id
を使うことができます。その説明はまた別の機会に、、、
<Route exact path="/users/:id" component={UsersShow} />
以上です。読んでいただきありがとうございました。
誤字、間違い等ありましたらコメント頂ければ幸いです。
参考記事
Discussion