はじめに
初めまして、仙台でバックエンドエンジニアをしている吉田です。
簡単にまず自己紹介をすると、JOINT CREWには2023年の7月に入社し、入社当初からお客様のECサイトの開発に携わっています。
その前は別の会社で5年間主にSESで色々なシステムの開発・保守を行っていました。
最後の2年間は受託開発で建設系のWebシステムの改修をフロントからバックエンドまで担当していたので、メインはJavaですが、ふわっとフロント周りも触れる、といった感じです。
今回はJavaScriptについては若干の理解がある私がモダンなJavaScriptライブラリとされるReactについて学んだ内容を少しだけ紹介します。
Reactでやっていることを、Reactを使わずに表現するとどうなるのか、という切り口からReactの特徴について考えます。
Reactについて
「Reactとはなんぞや」については巷にわかりやすい解説が色々ありますので、詳細はそちらに譲るとして、ここでは知らない方のためにざっくり概要を記載します。
ReactはFacebookが開発したJavaScriptライブラリです。
その大きな特徴はJavaScriptを使ってUI(ボタンやフォームなどの画面上の部品)を構成することができるということにあります。通常、JavaScriptは画面の動きの制御やバリデーションに使われます。
ReactはどのようにしてUIの構築を行っているのかについて簡単に触れていきます。
なお、「コンポーネント」や「仮想DOM」といったキーワードも重要なのですが、今回は情報量が多くなってしまうので割愛します。
JSXについて
ReactではJSXと呼ばれる構文を使います。HTMLのような見た目でJavaScriptを記述できる、という特徴を持っています。
見たほうが早いので、簡単な例を確認してみます。
const element = <h1>Hello,JSX!</h1>;
式の右辺は完全に見た目はHTMLの<h1>タグですが、これがJSXの構文です。
これが、ReactがJavaScriptでUIを構築できる秘密の1つになっています。
JSXは内部でJavaScriptのオブジェクトに変換され、画面の要素追加のために使われます。
Reactを使ったUIの出力
では早速Reactを使用して画面を作成するとどうなるのかを確認してみます。
※Reactを実行するには環境構築が必要です。
以下のような空の<div>タグのみが用意されたHTMLで考えます。( index.html )
<!DOCTYPE html>
<html lang="en">
<head>
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
当然、画面は以下のようにまっしろです。
では、Reactを使ってUIを構成してみます。( index.js )
import React from "react";
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));
const App = () => {
return (
<div>
<p>Fruits</p>
<ol>
<li>apple</li>
<li>banana</li>
<li>orange</li>
</ol>
</div>
);
};
root.render(<App />);
こちらを読み込むと画面には果物のリストが表示されます。
HTMLのコードは一切触らず、JavaScript(React)のみで画面項目の設定ができました。
Reactのコードのポイント
コードのポイントは3つです。
- Reactの要素を表示するためのノードを作成する
createRootという関数を使用することで、Reactの要素を表示するための部品を作成できます。引数には要素を追加したい部分のDOMを渡します。
今回はrootというidが振られた<div>タグを指定し、ここに要素を追加する準備をしています。 - JSXを返すfunctionを用意する
画面部品の描画にはJSXを使用するため、JSXを戻り値として返す関数を作成します。
今回はAppという関数をアロー関数式で定義しています。
なお、関数名の1文字目は大文字である必要があります。これはReact内で普通の関数なのか、画面描画に使いたいものなのかの区別をつけるためです。1文字目が大文字だと、画面描画に使うものだと判定されます。 - renderで要素を描画する
createRootで作成した要素のrenderを呼び出すことで、画面上に作成したUIを表示することができます。renderの引数としてJSXを渡します。
なお、作成した関数を使う場合はHTMLのタグのようにして記述します。このように記述すると、関数の戻り値であるJSXが引き渡されます。
Reactを使わないUIの出力
ここまででReactの概要について理解できたかと思います。
では、ライブラリを使わず、素のJavaScriptで同じ挙動を実現することはできるでしょうか。検証してみましょう。
const rootContainer = document.getElementById('root');
// divタグの要素を生成
const divElement = document.createElement('div');
// pタグの要素を生成
const pElement = document.createElement('p');
pElement.textContent = 'Fruits';
// olタグの要素を生成
const olElement = document.createElement('ol');
// liタグの要素を生成
const liElement1 = document.createElement('li');
liElement1.textContent = 'apple';
const liElement2 = document.createElement('li');
liElement2.textContent = 'banana';
const liElement3 = document.createElement('li');
liElement3.textContent = 'orange';
// olタグの子要素としてliタグを追加
olElement.appendChild(liElement1);
olElement.appendChild(liElement2);
olElement.appendChild(liElement3);
// divタグの子要素としてpタグとolタグを追加
divElement.appendChild(pElement);
divElement.appendChild(olElement);
// divタグをrootに追加
rootContainer.appendChild(divElement);
こちらを実行すると、Reactで書いたときと同じ画面出力を得られます。Reactで記載したときよりもコード量が多くなっているのがわかります。
実はJavaScriptも、DOMを操作することでHTMLに要素を追加する事ができます。
createElementで要素を生成し、その要素に対してtextContentなどの中身を追加していきます。親子関係を作りたい場合は、appendChildで親に対して子の要素を追加します。
上記コードはかなり長くなっていますが、大まかにはタグの生成、子要素の追加の繰り返しで構成されています。
最終的にrootの要素に対して生成した要素を追加することで、画面上にリストを描画しています。
ということで、Reactを使わなくても普通のJavaScriptでUIの構成ができることがわかりました。
しかし、これを実際の開発でやるとなるとかなり大変そうです。要素が増えたり、親子関係が変化した場合、修正に途方もない時間がかかりそうですし、バグも発生しそうです。
ReactによるUIの構成のメリット
Reactを使用した場合、使用しなかった場合について確認をしてきました。
Reactを使ったほうが圧倒的にシンプルでわかりやすい実装になることがわかりました。
では、そもそもHTMLで記載するのではなくReactを使う理由は何でしょうか。
いくつか理由があるかと思いますが、大きく2つ挙げられるかと思います。
理由1. 繰り返しや分岐が使える
HTMLには繰り返しや分岐がありませんが、ReactはJavaScriptなので繰り返しや分岐を使うことができます。
import React from "react";
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));
const FRUITS_ARRAY = ['apple', 'banana', 'orange'];
const App = () => {
const fruitsList = [];
for (const fruit of FRUITS_ARRAY) {
fruitsList.push(<li>{fruit}</li>);
}
return (
<div>
<p>Fruits</p>
<ol>
{fruitsList}
</ol>
</div>
);
};
root.render(<App />);
上記は繰り返しを使った例です。出力したいフルーツの名前をリストに詰めて、JSXの<li>タグを持ったリストを生成しています。そして、画面にJSXの<li>タグが詰まったリストを渡しています。
もし新しく要素を追加したい場合は、フルーツの名前のリストに追加すれば、returnの中身を修正することなく、項目の追加ができます。
理由2. 使い回しができる
要素を出力するには、JSXを返す関数を設定します。そのため、何度も同じことを書かなくても、関数の呼び出しさえすれば同じ出力を得ることができます。
以下は、フルーツのリストを2回出力する例です。
import React from "react";
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));
const App = () => {
return (
<div>
<p>Fruits</p>
<ol>
<li>apple</li>
<li>banana</li>
<li>orange</li>
</ol>
</div>
);
};
root.render(<div><App /><App /></div>);
フルーツのリストのJSXを返すApp関数を2回呼び出しています。
以下の通り、同じリストが2回出力されます。
リストのタグを何度も書かずとも、App関数を呼び出すことで全く同じ部品を出力することができます。
これを利用すると、部品ごとに関数を分けて分割したり、共通の部品として繰り返し使用したりすることができそうです。
まとめ
Reactの概要と、Reactを使わずにJavaScriptで同じ挙動を実現するとどうなるか、について確認してきました。また、なぜHTMLではなくReactなのか、についても確認しました。
JavaScriptでUIの構成も可能ですが、かなりコード量が多くなることがわかりました。
ReactはHTMLライクに書くことができるので、直感的にわかりやすいですし、修正も容易です。
また、Reatで書くことで部品ごとに関数を用意することで再利用性が上がったり、修正箇所が限定的になるという利点もあります。
Reactというライブラリを使うことで開発の幅がぐっと広がりそうです。
最後に
今回は、バックエンドメインの開発でフロントの知識がふんわりしている私が、ライブラリを使わないとどうなるのか、という観点でReactへの理解を深めようとしてみました。
私自身、まだまだReactの学習を始めたばかりで正直わからないことのほうが多いですが、何をしているのかの一端を垣間見ることができたので、今後の学習にも役立ちそうです。
ReactにはUIの構成だけでなく、他にも状態の管理など様々できることがあるのですが、それは別の機会に触れられればと思います。
最後までご覧いただきありがとうございました。