LaravelにReactを導入する時の手順〜ルーティングの設定

LaravelをAPIサーバーとして使う場合の忘備録として導入手順をメモしていこうと思います。

基本的には、以下ドキュメントを見れば書いてあることではあります。
[JavaScript & CSS Scaffolding](https://laravel.com/docs/6.x/frontend)

*この記事で使用しているLaravelのバージョンはLTSの`6系`です。
*Laravelのバージョンごとのドキュメントは以下を参考にしてみて下さい。
[Laravel Document](https://readouble.com/laravel/)

## Reactを導入する

まず、Laravelの`uiパッケージ`をインストールする必要があります。

```terminal
composer require laravel/ui:^1.0 --dev
```

次に以下コマンドでReactをインストールします。
Login機能を作成したい場合は、`--auth`を追記しましょう。
(5系で使えてた`make:auth`コマンドは、６系から削除されています)

```terminal
php artisan ui react --auth
```

その後、インストールメッセージに従って、npmコマンドを実行。

```terminal
npm install && npm run dev
```

yarn使う場合は以下の通り

```terminal
yarn install && yarn dev
```

これでLaravelでReactを使えるようになります。
`resources/js/components`配下の`Example.js`が、Reactに書き換わってることが確認できると思います。

## Reactでページを作ってみる

折角なんで、実際にReactでviewを書いて、確認してみましょう。

`resource/js/app.js`には既に、Exampleを読み込む設定がされていますが、これを`App.js`に書き換えておきましょう。

```javascript:app.js
/**
 * Next, we will create a fresh React component instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */

require('./components/App'); //ここをAppに書き換える
```

まず、ルートの定義をします。

```php:web.php
Route::get('/{any}', function(){
    return view('App');
})->where('any', '.*'); //補足：.*は、正規表現で0文字以上の任意の文字列を意味する
```

次に、viewとcomponents配下に、`App.js`を新規作成します。
まずは、ファイルの変更を監視するために、以下コマンドを入力。

```terminal
npm run watch 
```

```html:app.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>{{ config('app.name', 'React導入テスト') }}</title>
    <script src="{{ asset('js/app.js') }}" defer></script>
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app"></div>
</body>
</html>
```

```react:App.js
import React from 'react';
import ReactDOM from 'react-dom';

const App = () => {
    return(
        <p>表示されてる？</p>
    )
}

if (document.getElementById('app')) {
    ReactDOM.render(<App />, document.getElementById('app'));
}
```

これで一旦、表示は確認できたかと思います。

### ページ遷移のために、`react-router-dom`を導入

次にページ遷移の確認を。
Routingライブラリの `react-router` `react-router-dom`をインストールしておきましょう。
[react-router](https://www.npmjs.com/package/react-router)
[react-router-dom](https://www.npmjs.com/package/react-router-dom)


```terminal:npmの場合
npm install react-router react-router-dom
```

```terminal:yarnの場合
yarn add react-router react-router-dom
```


検証用に以下、コンポーネントを作成。

```react:GlobalNav.js
import React from 'react';
import {Link} from 'react-router-dom';

const GlobalNav = () => {
    return(
        <nav>
            <ul>
                <Link to="/">
                    <li>Top</li>
                </Link>
                <Link to="/about">
                    <li>About</li>
                </Link>
            </ul>
        </nav>
    )
}

export default GlobalNav;
```

```react:Top.js
import React from 'react';

const Top = () => {
    return <h1>TopPage</h1>
}

export default Top;
```

```react:About.js
import React from 'react'

const About = () => {
    return <h1>About</h1>
}

export default About;
```

App.jsで上記コンポーネントをインポートします。

```react:App.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route, Switch} from 'react-router-dom';

import GlobalNav from './GlobalNav';
import Top from './Top';
import About from './About';

const App = () => {
    return(
        <BrowserRouter>
        <React.Fragment>
            <GlobalNav />
            <Switch>
　　　　　　　　　　{/*完全一致のため、exactを付与*/}
                <Route path="/" exact component={Top} /> 
                <Route path="/about" component={About} />
            </Switch>
        </React.Fragment>
        </BrowserRouter>
    )
}

if (document.getElementById('app')) {
    ReactDOM.render(<App />, document.getElementById('app'));
}
```

#### `react-router-dom`のタグについて補足

##### BrowserRouter
ルーティングを定義するために `<BrowserRouter>`か`<HashRouter>`、いずれかのコンポーネントを使用します。
BrowserRouterは、[History API](https://developer.mozilla.org/ja/docs/Web/API/History_API)を、HashRouterは、[Window.location](https://developer.mozilla.org/ja/docs/Web/API/Window/location)を利用しています。

##### Switch
`<Switch>`内にルーティングを記述すると、urlにマッチした最初のルーティングだけがレンダリングされます。
<Switch>タグで囲わなかった場合、上記例で言うと、TopコンポーネントとAboutコンポーネントの文字列が同時に表示されてしまうことになります。

##### Route
URLpathと、URLが一致した際にレンダリングするコンポーネントを指定します。
exact pathは、URLを完全一致させたいときに利用します。

以上、簡単にですが、Laravel内でReactを利用する方法を簡単にまとめました。
![画面収録 2020-07-18 16.07.09.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33632/a6cf18c0-97b7-6863-ac58-efd92144c016.gif)