はじめに独り言
公式サイト含めネット上のReact入門解説情報は全くもって入門させる気が無い。なぜこんなにわかりにくい説明が多いのか謎。いや、それで理解できない自分がおかしいのか??
連携方法
Laravel で React を使う方法はいくつかある。正直 React を使うならフレームワークは他のもの(NestJSとか良さそう)を使ったほうが React との相性は良いと思う。ここでは blade にReactコンポーネントを載せるという面倒な方法でやっている。ルーティングは Laravel で行い、画面には blade が返され、コンテンツが React という構成になるので Single Page Application ではない。でもSPAってそんなにこだわる部分かなぁ、と思っている。
コンポーネント
機能を持った html タグのまとまりをコンポーネントと呼び、webページをコンポーネントを並べてデザインするという考え方。
コンポーネントは javascript 関数として定義される。ファイル名、関数名は大文字で始めないと正常に動作しない。
import React from 'react';
export default function SampleComponent() { // コンポーネントは大文字で始める
// 機能部分の記述
return(
// jsx(htmlタグみたいなやつ)の記述
);
}
イベント処理の違い
javascript は htmlタグ や文章をリアルタイムで書き換える言語として生まれ、発展してきた。そのためのライブラリも充実している。jQueryとか代表的。
でも React はその歴史を全て塗り替えるような考え方をしている。
たとえば、html に機能を実装させる方法として、以下のようなメソッドは使用しない。
document.element.addEventListener // イベントを追加
document.element.innerHtml // 書き換え
では React ではどうやって機能を実装するかというと、関数として定義する。
import react from react;
export default function SampleComponent() {
// 機能部分の記述
const eventHandle = () => {
// 何か処理をする
}
return( // return 内は div タグで囲む(最上位タグは必ずひとつ)
<div>
<button
onClick={eventHandle} // イベント関数を指定
>
ボタン
</button>
</div>
);
}
イベントはタグの属性として指定する。次の章になるが最初は以下2つを攻略する。
- クリックしたら何かが起こる系:onClick
- 値が変わったら何かが起こる系:onChange
関数の書き方
変数に無名関数を代入する書き方がよく使われる。
function MyFunc(x) { return x + 1; }
const Myfunc = (x) => { return x + 1; } // 変数に無名関数を代入する記述方法
const MyFunc = x => x + 1; // 引数が1つの場合カッコや return すら省略される
上記3つは同じ。下2つの書き方をよく使う。慣れるまでは一見何をしているコードなのかわかりにくいよね。
Laravel 12 で React を使えるようにする
対応の問題でnodejsは version 22 を、tailwindcssは version 3.4 をインストールする。 Laravel のインストールはcomposerコマンドで行う。laravel newコマンドを使ってインストールオプションのReactを選択するとInertia.jsを使ったSPA環境になるので、今回とは環境構成が異なる。以下のコマンドでインストールとアプリケーションを作成する。
composer create-project laravel/laravel app-name
作成したアプリケーションのルートディレクトリへ移動して以下を実行する。
npm install react react-dom
vite.config.jsに以下の設定があるか確認する。上記のコマンドを実行すれば、自動で記述されたような...。特に注意すべきポイントとして、app.jsではなく、app.jsxになっていることを確認する。
... 他の部分省略 ...
input ['resources/css/app.css', 'resources/js/app.jsx']
resources/js配下のファイル名を確認し、app.jsではなくapp.jsxが存在するかを確認する。ファイル名がapp.jsになっている場合はリネームしてxを付け足す。
この環境の React の動作
Controler が return view して blade が表示されると、最初にresources/js/app.jsxが走る。したがって、すべてのコンポーネントの呼び出しはapp.jsxで指定する。
import ./bootstrap.js; // 最初から書いてある行
import React from "react"; // 追記
import ReactDOM from "react-dom/client"; // 追記
import ./components/MyComponent; // 自作したコンポーネントをインポート
const componentElement = document.getElementById('tag-id'); // blade のタグに記述されているID属性を取得して
if (componentElement) { // 開いているbladeにタグidが存在したら
const root = createRoot(componentElement);
root.render(<MyComponent />); // Reactコンポーネントを描画する
}
で、この記述方法だとコンポーネントが増えてきたときにどの blade にアクセスしても全てのコンポーネントをインポートするという無駄な処理が発生する。SPAではないので関係ないコンポーネントは読み込む必要はない。無駄を発生させないために、該当するidタグが存在する場合にだけ必要なコンポーネントを読み込むようにする。
import ./bootstrap.js;
import react;
import react-dom;
const componentElement = document.getElementById('tag-id');
if (componentElement) {
// idがある場合のみコンポーネントをインポート
import('./components/MyComponent').then(({ default: MyComponent }) => {
const root = createRoot(componentElement);
root.render(<MyComponent />);
});
}
さらに、コンポーネントを増やすたびにこのコードを追記していくのはちょっとキツい。ということで、関数化する。
function mount(id, importer) {
const el = document.getElementById(id);
if (el) {
importer().then(({ default: Cmp }) => {
createRoot(el).render(<Cmp />);
});
}
}
mount('tag-id', () => import(./components/MyComponent)); // 1行で書けるようになった
これでコンポーネントを追加したとき、1行の記述で設定できるようになった。
この1行を追記する作業、忘れやすいので注意する。
コンポーネントの作成
さっそくコンポーネントを作成する。
resources/js/components/ExampleComponent.jsxとしてファイルを作成する。
import React from 'react';
export default function ExampleComponent() { // 大文字で始める
return (
<div>
Example Component
</div>
);
}
これは「Example Component」という文字列を表示するコンポーネント。機能は何もない。
「return」で記述するHTMLタグっぽいやつはjsxと呼ばれている。
コンポーネント記述のルールは以下の通り。
- コンポーネント(定義関数)名は必ず大文字で始める
- ファイル名も必ず大文字で始める
-
app.jsxでインポートできるようにコンポーネント関数はexportする - return では必ずひとつのタグを返すように記述する(divタグで囲めばよし)
- return では必ず閉じタグが必要
変数に関数を代入する記述でコンポーネントを定義する場合、必ず最後にexportする。
const ExampleComponent = () => { // 必ず大文字で始める
コンポーネントの内容
}
export default ExampleComponent; // const で定義した場合はこの記述が必要、忘れやすいんだよなぁ
jsxは小文字で始まるものをhtmlタグ、大文字で始まるものをコンポーネントとして認識する。なのでコンポーネント名は大文字で始める必要がある。
閉じタグが無いタグは以下のように記述する。
<img />
<input />
// 閉じタグがないものには /> を記述する
bladeファイル にはコンポーネントを埋め込む部分に以下を記述する。
<div id="example"></div>
app.jsxにExampleComponentを呼び出す記述を忘れないように。
mount('example', () => import(./components/ExamleComponent));
全て記述が終わったらもちろんコレを実行。
npm run build
次に続く。