【1日目】React初学者が1週間でどこまで出来るか挑戦(環境構築と基礎編)

はじめに

前から興味があったReactを始めてみました。新しい技術を勉強するのが結構久しぶりで、「1週間でどれくらい出来るようになるんだろう」と気になったので、勝手に7days challengeと題して勉強始めてみました!

docker環境でLaravelプロジェクトをインストールした状態から始めます。途中で知らない知識など寄り道して調べながら進めています。初日の進捗はざっくり以下の通りです。

  • ReactをLaravelで使えるようにする
  • Reactのコンポーネントの基礎の基礎

この学習に使ってるGitHubリポジトリも公開してます: GitHub - rk-techs/study-react-laravel

(以下、学習メモの文章部分は常体になります)

React, Laravelの環境構築

前提:

  • docker-laravelをクローンしてDocker環境構築済み
  • Laravelプロジェクトはインストール済み

開発環境:

  • MacBook Air: M1, 2020
  • macOS: Sonoma 14.0
  • Docker: 24.0.2
  • Docker Compose: v2.18.1

構築内容:

  • PHP: 8.2.x
  • MySQL: 5.7
  • nginx: 1.25.1
  • composer: 2.6.x
  • Laravel: 10.x

Reactをインストール

まずはLaravel公式ドキュメントを確認、検索窓からReactを検索。

「Starter Kits」 > 「Breeze & React / Vue」に関連しそうな説明があった。

Laravel Breeze also offers React and Vue scaffolding via an Inertia frontend implementation.

Inertia... 初見の言葉が出てきたため確認。

Inertiaは従来のサーバー駆動型webアプリを構築する新しいアプローチで、modern monolithと呼ぶらしい。また、「IntertiaはクライアントサイドのルーティングがなくAPIも必要としないため、コントローラーやviewなどをいつも通り簡単に構築できる」とある。

Inertiaについてはここまでにして、一旦Laravelドキュメントに戻る。

Reactはbreez:installコマンドを実行時に選べると説明がある。

you may select the Vue or React frontend stacks when executing the breeze:install Artisan command.

ただ、ここでbreeze:installコマンドを実行しても「breezeコマンドなんて無い」とエラーになる。

ERROR  There are no commands defined in the "breeze" namespace.

一度ドキュメントの最初の方に戻り、Breezeパッケージのインストール方法を確認: Installation

composer require laravel/breeze --dev

実行してcomposer.jsonに依存関係が追加されることを確認。

"require-dev": {
    "laravel/breeze": "^1.24",

再度Artisanコマンドを実行。

php artisan breeze:install

すると以下のプロンプトが表示される。ここでReact with Inertiaを選べるということらしい。

 ┌ Which Breeze stack would you like to install? ───────────────┐
 │   ○ Blade with Alpine                                        │
 │   ○ Livewire with Alpine                                     │
 │ › ● React with Inertia                                       │
 │   ○ Vue with Inertia                                         │
 │   ○ API only                                                 │
 └──────────────────────────────────────────────────────────────┘

次にオプションを聞かれる。

 ┌ Would you like any optional features? ───────────────────────┐
 │ › ◻ Dark mode                                                │
 │   ◻ Inertia SSR                                              │
 │   ◻ TypeScript (experimental)                                │
 └──────────────────────────────────────────────────────────────┘

Inertia SSRがよく分からず、LaravelドキュメントにInertia公式へのリングがあるため確認。

SSRとは、Server-side Renderingのこと。「JavaScriptのページを事前にサーバー側でレンダリングして、ページを開いたときには完全にレンダリングされたHTMLを受け取ることができる」とある。

Server-side rendering pre-renders your JavaScript pages on the server, allowing your visitors to receive fully rendered HTML when they visit your application.

SSRはページをバックグラウンドでレンダリングするためにNode.jsを使うようだ。

Server-side rendering uses Node.js to render your pages in a background process

この辺りは、クライアントとサーバーの処理について前提知識がないと厳しそう。今回はSSRではなく、CSR(Client-side Rendering)でよさそうという情報だけ得たためオプションは選ばずそのまま進む。

  • SSR :  サーバー側でHTMLを生成して返しレンダリング
  • CSR : ブラウザ上でJavaScriptを実行してHTMLを生成してレンダリング

次にテストのフレームワークを聞かれる。ここではPHPUnitを選択。

 ┌ Which testing framework do you prefer? ──────────────────────┐
 │ › ● PHPUnit                                                  │
 │   ○ Pest                                                     │
 └──────────────────────────────────────────────────────────────┘

以上でインストール完了。

要約

Laravel Breeze パッケージのインストール。まずはcomposerで依存関係の追加。

composer require laravel/breeze --dev

artisanコマンドでbreezeのインストール実行。

php artisan breeze:install

プロンプトで選択肢を聞かれるのでReactを選択。他のオプションはそのまま進む。

 ┌ Which Breeze stack would you like to install? ───────────────┐
 │   ○ Blade with Alpine                                        │
 │   ○ Livewire with Alpine                                     │
 │ › ● React with Inertia                                       │
 │   ○ Vue with Inertia                                         │
 │   ○ API only                                                 │
 └──────────────────────────────────────────────────────────────┘

Viteの設定

docker環境でViteを使う場合、vite.config.jsを正しく設定する必要がある。以下のコードを追加してホットリロードを有効にする。(ここは以前詰まって調べた経験があるため今回はショートカット)

server: {
    host: true,
    hmr: {
        host: 'localhost',
    },
},

追加後のvite.config.js:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';

export default defineConfig({
    plugins: [
        laravel({
            input: 'resources/js/app.jsx',
            refresh: true,
        }),
        react(),
    ],
    server: {
        host: true,
        hmr: {
            host: 'localhost',
        },
    },
});

インストール後の構成確認

breezeインストールによってファイルが大量に追加された。まずはweb.phpを確認。ルートページではresources/js/Pages/Welcome.jsxが表示されているみたい。

Route::get('/', function () {
    return Inertia::render('Welcome', [
        'canLogin' => Route::has('login'),
        'canRegister' => Route::has('register'),
        'laravelVersion' => Application::VERSION,
        'phpVersion' => PHP_VERSION,
    ]);
});

Inertiaは初めて使うため、InertiarenderメソッドのDocコメントで文法を確認。

Inertia\Inertia::render

<?php
public static function render($component, $props = []) { }
@param string $component

@param array|\Illuminate\Contracts\Support\Arrayable $props

@return \Inertia\Response

次に、ログインページを確認。URLは/loginで、routes/auth.phpに定義されている。

Route::get('login', [AuthenticatedSessionController::class, 'create'])
            ->name('login');

AuthenticatedSessionControllercreateメソッドを確認すると、やはりInertiarenderメソッドでResponseを返している。

public function create(): Response
{
    return Inertia::render('Auth/Login', [
        'canResetPassword' => Route::has('password.request'),
        'status' => session('status'),
    ]);
}

resources/js/Pages/Auth/Login.jsxを表示しているみたい。renderメソッドの第二引数に表示したいjsxファイルのパスを渡せばよさそう。(Pagesディレクトリ起点?)

Reactの基礎を学ぶ

React公式ドキュメントの「LEARN REACT > Your First Component」から確認していく。

ポイント:

  • ComponentはReactのコアであり、UIを作る基礎部分になる

コンポーネントのExport

export defaultによって、ファイル内のmainの関数を他のファイルでインポートできるようにしているみたい。(React特有の構文ではなくてJavaScritpの一般的な構文)

関数の定義

function 関数名() { } はJavaScriptの関数と同じだが、大文字で始めること!

// Login.jsxの例
export default function Login({ status, canResetPassword }) {
  // ...
}

マークアップ

コンポーネントはHTMLのようタグの記述を返すが、内部的にはJavaScriptらしい。この構文をJSXと呼ぶみたいだ。

  • returnは一行で記述する
  • 一行に収まらない時は、カッコ()で囲うこと
// Login.jsxのLoginメソッドの例

return (
    <GuestLayout>
        <Head title="Log in" />

        {status && <div className="mb-4 font-medium text-sm text-green-600">{status}</div>}

        <form onSubmit={submit}>
          // ...省略
        </form>
    </GuestLayout>
);

コンポーネントを使う

上記Login.jsxの記述を参考に

  • 小文字で始まるタグは通常のHTMLタグとして認識される(<div>など)
  • 大文字で始まるものはReactのコンポーネントとして認識(<GuestLayout><Head title="Log in" />など)

コンポーネントのネストと整理について: (Nesting and organizing components

  • コンポーネントは同じファイルに複数書ける
  • ファイルが大きくなったら単一のファイルに分けたらいい
  • コンポーネントはネストしない!(コンポーネントは他のコンポーネントをレンダリングできるけど、コンポーネントの中に他のコンポーネントの定義は書かないこと)

まとめ

今日は環境構築とReactの本当に触りの部分だけでした。Reactの公式ドキュメントは分かりやすい印象を受けました。チュートリアルのチャプターが結構な量あり、どこまで進むか分かりませんが、「1週間」という区切りでどこまで出来るか試してみます。

連載記事

  1. 【1日目】React初学者が1週間でどこまで出来るか挑戦 ★今回
  2. 【2日目】React初学者が1週間でどこまで出来るか挑戦