Laravel(6.x) React+Material UIでGridデザイン

近頃Reactが流行っていますよね
LaravelでReactを使う方法はよく見かけるのですがじゃあ
Reactで具体的にどんなViewを見せてみるかまであまりなかったので
今回はMaterial UIのGridListを使った画像一覧画面を作ってみたいと思います

この記事をすすめるとどうなる

以下のようなGridスタイルの画像一覧が作成できます

Reactを導入

まず、Laravelの表示ビューとしてReactを使えるようにします

composerでlaravel uiパッケージをインストールします
6系では以下コマンドでインストールします

composer require laravel/ui "^1.0" --dev

次にartisanコマンドを使ってuiをreactに設定します

php artisan ui react
$ php artisan ui react
React scaffolding installed successfully.
Please run "npm install && npm run dev" to compile your fresh scaffolding.

次に、npm install && npm run dev を実行してコンパイルします
必要なnpmパッケージがインストールされ、reactで記述されたjsファイルが
コンパイルされます

npm install && npm run dev

コンパイルされると、 public/css、public/jsにコンパイル結果野ファイルが
出力されます

Material-UIを導入

Material-UIはすでにデザインも適用されたコンポーネントが多数入った
パッケージです
まずは以下コマンドでコアパッケージをインストールします

npm install @material-ui/core

ルーティング、コンパイルの設定をする

React、Material-UIを使えるようにしたので
新しいページを作成して、GridListを使った
一覧画面用のコンポーネントを作成します

routes/web.php

初期は、welcomeのみ入っている状態なので
以下を追加します

Route::get('/list', function () {
    return view('list');
});

resources/views/list.blade.php

resources/views配下にroutesで指定したbladeファイルを作成します
ファイル名:list.blade.php
内容は以下です、シンプルなHTMLで
コンパイル出力するjsファイルのみ指定しておきます

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Grid Image List</title>
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<script src="{{ asset('/js/list.js') }}"></script>
</body>
</html>

resources/js/list.js

コンパイル対象のjsファイルを作成します
中身は以下です

require('./bootstrap');
require('./components/List');

webpack.mix.js

ビルドツールのwebpackに、追加したresource/jsをコンパイルするように
指定します
2行目が追加したものです

mix.react('resources/js/app.js', 'public/js')
 .react('resources/js/list.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');

コンポーネントを作成する

最後にMaterial-UIを使って画像一覧を表示するコンポーネントを
作成します

resources/js/components/List.jsx

resource/js/components配下にList.jsxを作成します

中身は以下です

import React from 'react'
import ReactDOM from 'react-dom'
import { makeStyles } from '@material-ui/core/styles'
import GridList from '@material-ui/core/GridList'
import GridListTile from '@material-ui/core/GridListTile'
import sample1 from '../../assets/images/sample1.jpg'
import sample2 from '../../assets/images/sample2.jpg'
import sample3 from '../../assets/images/sample3.jpg'
import sample4 from '../../assets/images/sample4.jpg'
import sample5 from '../../assets/images/sample5.jpg'
import sample6 from '../../assets/images/sample6.jpg'
import sample7 from '../../assets/images/sample7.jpg'

const sampleImageList = [
    { title: "サンプル1", img: sample1, cols: 2 },
    { title: "サンプル2", img: sample2 },
    { title: "サンプル3", img: sample3 },
    { title: "サンプル4", img: sample4, cols: 2 },
    { title: "サンプル5", img: sample5, cols: 2 },
    { title: "サンプル6", img: sample6 },
    { title: "サンプル7", img: sample7, cols: 2 },
]

const useStyles = makeStyles((theme) => ({
    root: {
        display: 'flex',
        flexWrap: 'wrap',
        justifyContent: 'space-around',
        overflow: 'hidden',
    },
    gridList: {
        width: 720,
        height: '100%',
    },
}));

export const List = () => {
    const classes = useStyles();

    return (
        <div className={classes.root}>
            <GridList cellHeight={280} className={classes.gridList} cols={3}>
                {sampleImageList.map((tile) => (
                    <GridListTile key={tile.img} cols={tile.cols || 1}>
                        <img src={tile.img} alt={tile.title} />
                    </GridListTile>
                ))}
            </GridList>
        </div>
    );
}

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

画像を配置する

上記List.jsxのファイルにサンプル画像を7つ定義しました
実ファイルがないとエラーとなるため適当な画像を用意してください

resourcesの直下に assets/images とディレクトリを作成し画像ファイルを
配置しましょう

importで呼び出された画像ファイルは、ビルド時にassets下のものを
publicに自動でコピーしてくれます

ビルドして画面を確認

npm run dev または npm run watch でビルドします
watchでビルドしておくほうが、ファイルの変更があれば再度自動で
ビルドしてくれるので楽になります
さらに別ターミナルでphp artisan serveでサーバを起動します

npm run watch
php artisan serve

http://localhost:8000/list にアクセスしてみましょう
以下のように画像一覧が表示されていれば成功です!

まとめ

LaravelでReactに簡単に切り替えられるのは便利ですよね
ただゼロからコンポーネントを用意して、デザインをあてて・・・というのは
結構たいへん

Material-UIなどのモダンなデザインで作られたコンポーネントパッケージ
を使うことでさくっと見栄えの良いページが作れます

他にも様々なコンポーネントを用意してくれてるのでぜひ試してみてください!