はいさい!ちゅらデータぬオースティンやいびーん!
今回の記事は筆者に珍しく、技術紹介ではなく、僕の個人的な意見を書きます。あくまでも、自説です。
React自体は画期的で、プログラミング界に貢献したプロジェクトだと思っていますし、完全に否定したいわけではありません。
Reactに対する違和感=芽生えては大きく育った種
筆者はReactがとても好きでした。JavaScriptが好きになったきっかけもReactでした。何から何までもReactで書き直して、Custom Hooksを作って、refを子部品に渡したり、バリバリ満喫していました。
Vueも仕事の関係で習得せざるを得なくなったのですが、Vueは最高に大嫌いでした。これならReactで書き直してやるぅ!と思ったりも。
Reactについて社内でも導入を推進したり、React入門の勉強会を開いたりもしています。
しかし、そんな筆者は、最近になって、Reactに対してさまざまな疑問が雑草のように思考のあちらこちらから生えてきており、草刈りが間に合わない次第です。
最もReactに対して受け入れられないのは以下の項目です。
- なぜDOMのEvent制度を使わない?
- JSXはなぜテンプレートでできなかったのか?
- DOM、いじるなよ。な?いじるなよ。
- Virtual DOMは早くないよ?
- Hooksは、本当にコードをわかりやすくしているのか?
- Contextもあり、Reduxも?
- 効率のいいフレームワークというよりは、銘柄になっていること
- Meta(お前だぞ、悪名高きFacebook)が作っていること
これらについて筆者の意見を本記事で書いていきます。
なぜDOMのEvent制度を使わない?
JavaScriptには立派なものがあります。それは、パッケージをインストールせずに使えるものです。
そうです。DOMでございます。
DOMにはさまざまな標準機能があり、JavaScriptの長い歴史と共に磨かれてきています。特にここ5年間ではブラウザ機能が非常に便利になっており、第三者パッケージをコードベースに入れなくても、大体のことはできる。
その中の最もJavaScriptの本質に近いのは、DOMのEventインターフェイス。
もちろん、こんな基礎的な、標準機能はReactの基礎にもなっているはず。そうですよね?
違います。
Reactは、独自のシステムで同じことをやって、Stateを変えたら、Virtual DOMを作り替えて、変わったところを本物のDOMに反映させているのです。
Reactのコア、内部ではEventインターフェイスが基本的に使われておらず、React以外のEventインターフェイスで動いている世界と相性よく付き合わせるためには工夫が必要です。
つまり、useEffect、useRefを使わないと、ブラウザの最も基本的な機能をReactでは使えないのです。
これって、変だと思いませんか?
Vue、Svelte、Litなど、他のフレームワークは相性よくEventインターフェイスをフレームワークの内部で組み込んでおり、また、Vueなどの子部品からEventを配信したり、そのEventを親部品で受信したりすることはフレームワークの基礎になっています。
英語では以下のようなことわざがあります。
Don't reinvent the wheel.
これは、うまくできているものをわざわざ作り直さなくていいよ、というもので、Reactはこの掟を破っていると思います。
もう一つ(アメリカ)英語のことわざがあります。
If it ain't broken, don't fix it.
これは筆者のおじいがよく筆者に説いていたものです(筆者は直すと言ってなんでも分解しては壊すくせがありました)。
まさにこれだと思います。
DOMのEventインターフェイスは壊れていない。とても優れたシステムです。なので、React、格好つけないでそれを使ってください。
JSXはなぜテンプレートでできなかったのか?
JSXは筆者はそこまで嫌いではありません。また、JavaScriptの中にHTMLがあることも特に不快でもないです。これ自体は問題ではないと思います。
問題は、JSXです。
JSXは、JavaScriptの中でReact.createElement()を呼ばずに、もっとHTMLのように書けるように開発された技術です。
もっとHTMLのようにはなっているが、HTML5の基準には一切従っていないのです。
HTMLではこう書きます。
<label class="important" for="name">名前</label>
<input id="name" type="text">
しかし、Reactではこう書かされます。
return (
<div>
<label className="important" htmlFor="name">名前</label>
<input id="name" type="text">
</div>
)
classNameとhtmlForは、JavaScriptだと勘違いされないように、名前を変えないといけなかったのです。
なぜ?
JSXは訳のわからない見た目をしたJavaScriptの化け物だからです。Babelなど、JSXを翻訳してくれる技術も必要になってくることは脇において、JSXではさまざまな落とし穴があります。HTML5の標準に沿っていないので、Reactでしか活かされない知識を勉強しないといけないです。
普通のJavaScriptでは、JSXのようなものを書かず、テンプレートリテラルを使います。テンプレートリテラルはES6で導入されて久しく、一般的に使われています。
Litではとても綺麗にテンプレートを導入しています。EventListenerも、値も、テンプレートリテラルで導入できます。
import { html, render } from "lit-html";
render(html`
<label class="important" for="name">名前</label>
<input @input=${handleInput} id="name" type="text" .value=${inputValue}>
`)
Vueでは、<template>タグでHTML5の基準に沿って本物のHTML5を書けます。
また英単語を紹介します。
Over-engineered
過剰に設計された、過剰に詳細にこだわった、というような意味です。
ReactのJSXは、over-engineeredなのです。
DOM、いじるなよ。な?いじるなよ。
これは一番気に食わないことです。
Reactでは、DOMをいじらずに全てReactの機能で動かすのが美学とされています。
しかし、DOMをいじるのは、当たり前のことです。
実際、我々Web開発の連中は、DOMと仲良く付き合って、その豊富な機能を使わせてもらわねばならんのじゃ。
しかし、Reactでは?
DOMをいじるな。
DOMをいじるなんて、ダサい。こいつ、粋じゃないな、わかってないな。
という風潮は強くある気がします。
と言っても結局DOMをいじらないといけないことは実際にあります。例えばwindowにEventListenerをつけるとか、Intersection Observerで<div>が画面に入ってきたかどうかを見てみるなど。
こういう時は、不器用にuseEffectとuseRefを使わざるを得なく、急速的に要求される技術が莫大に増えていきます。
ReactのLife Cycleの中でしかDOMをいじれず、とても窮屈に思ったことがありませんか?
Vueも同じくrefを使う必要はありますが、色々ともっと合理的になっていて、DOMにより近いフレームワーク。
ReactではブラウザAPIなど、使うのにハードルが非常に高い。
Virtual DOMは早くないよ?
Reactは以前は強気にVirtual DOMは実際のDOMを変更するより効率が良く、速くできると主張していました。
最近は、そう言わなくなったのです。
なぜ?
馬鹿げた話だったからです。
速くないし、効率は良くない。
const [name, setName] = useState("Austin");
return (
<div>{name}</div>
)
上記で名前を変えるのに、setNameを読んで、Reactが変更したと思われる部品を再レンダーし、Virtual DOMを再度構築してくれる。
それから、実際のDOMとVirtual DOMを比較して、変わったところを見つけてから、変わったところを更新する。
nameを変えるのに、複数の段取りがありますよね?筆者も内部を理解していない。しかし、間違いなくさまざまな計算はされているはずです。nameを変えるだけで煩雑なプロセスが裏で動いているのは言うまでもないでしょう。
DOMを変えるのはどうでしょうか?
const div = document.querySelector("div");
div.textContent = "New Austin!";
終わりました。
さて、どちらが早いでしょうか?
Virtual DOMは速いというのは、迷信です。
Hooksは、本当にコードをわかりやすくしているのか?
Reactは最初、classで部品を書いていました。
しかし、オブジェクト志向がJavaScriptらしくないということで、もっとJavaScriptらしい概念を生み出してくれたのです。
そう、Hooksです。
useStateがその代表ですが、JavaScriptの関数を再度実行しても魔法で変わらないデータを保持する手法です。これは魔法です。
Hooksがどうやって動いているかい?魔法です。
その魔法の蓋を開けるな。
開けたい?
いいよわかった、魔法じゃないよ。実はJavaScriptです。
どんなJavaScript?
JavaScriptのLexical Scopeだよ
Lexical何?
...だから魔法なんだよ。
ReactのHooksの仕組みを説明するとこんな会話になるかと思います。JavaScriptには、関数を起こした時に、その周辺の定数などを関数のスコープとして保持するLexical Scopeというのが設計されていて、Reactはそれを理解を超えた使い方でHooksを実装している。
Hooksの仕組みは非常に複雑なのです。
その非常に複雑なHooksを導入した理由は?
厄介で禁物のオブジェクト指向をJavaScriptに持ち込みたくないからです。つまりES6から標準になっているclass構文が嫌だから、またPrototype志向もわからないから、Hooksを作ったのです。
Hooksを使って独自のCustom Hooksを作ることもできます。これも部品からロジックを抽出して使い回しができるように勧められている手法ですが、
読者に聞きます。
Custom Hooksで自分が書いたコードがわかりやすくなった試しはありますか?
筆者は、書いている当時は、自分の賢さに酔って、素晴らしいものを作ったといつも思っていましたが、数ヶ月後にそのコードベースで作業するといつもこうなります。
どこで何が起きているのかわからない
筆者の書き方が良くないというのは間違いなくあるでしょうが、Custom Hooksでは、一つの部品で必要なロジックが違うところにあるので、わかりにくくなるのは確かです。
オブジェクト指向のClass構文では、その部品にまつわる全てのロジックをその部品にくっつけることができるので、格好悪くても理に適っているように思います。
筆者は、以前はどのような些細なロジックでも、抽出しては実際に使われているところと違う場所に保存するという癖があって、今となってはとても反省しています。
ロジックは、使われるところで、まとめるべきものです。Custom Hooksはその反対のことをしています。
Hooks自体も、オブジェクト指向のいいところを否定して、コードを難解にしているのだと思いませんか?
効率のいいフレームワークというよりは、銘柄になっていること
これは、サービスを使っているユーザーへのアピールというより、開発を提案する時の話かと思います。
欧米で大人気の、あのFacebook・Metaが開発したReactを使って開発しますから、いいものができますよ!
このような提案をしている気がします。つまり、Reactの銘柄を売っているような気がします。
銘柄で適切な技術の査定をするべきじゃないのだと思います。
いいUXを意識して作るべきです。それこそがユーザーの求めていること。
Reactは重く、底辺の携帯などでは鈍いので、必ずReactがいいとは限らない。
Contextもあり、Reduxも?
Reactには中央ステートを管理するためのuseContextがあります。それを使うことより、ほとんどのプロジェクトではRedux(後継者のRecoilか?)を採用しています。
useContextはReactの標準ライブラリーなので、適切に使う場面があります(特にユーザー認証の状態をアプリ全体で管理するために)。
Reduxは?
英語でboilerplateという単語があって、プログラミングにおいては、フレームワークなど、第三者パッケージのことを指します。何かをするために導入したライブラリーのことです。
boilerplateが増えると、ユーザーがダウンロードしないといけないパッケージサイズが増えるほか、ユーザーの端末に課している負担も増大。
また、プロジェクトに関わっているメンバーが学習しないといけない技術スタックにも入るので、負債になります。
余計なboilerplateは避けたいものです。
Reduxは、boilerplateです。
これはReactへの疑問というより、Reactの一般的な使い方に対する疑問です。上記のHooksの話と同様に、部品に関わるロジックはできるだけ部品ごとにまとめたいものです。これは保守の観点から言っていることです。
部品のファイルを開いた時に、その部品が何をするか、その部品を動かしているロジックが何かを見たいのです。
しかし、Reduxは中央ステートと言って、漠然としたところにそういったロジックをごちゃ混ぜ、チャンプルにするのです。
筆者はこれが個人的に嫌なので、個人の意見として考えてください。
本当に中央ステートは必要ですか?
Meta(お前だぞ、悪名高きFacebook)が作っていること
これは、アメリカ人の筆者が特別に思うことで、技術的な話では一切ないです。
Facebookは、倫理的に問題のある企業です。
日本では、Facebookはアメリカほど利用されていないので、他人事かと思いますが、アメリカではFacebookは、ヘイトスピーチ、未成年保護を皮切りに、さまざまな社会問題になっています。
Metaも、自分らの提供するサービスが社会問題になっていることを認識しています。
しかし、何も対策をしないという選択をしているのです。
なぜ?ヘイトスピーチは儲かるからです。
本屋さんにヘイト本が並んでいるのと一緒です。商業主義なのです。
Twitterは、上記のような社会問題に対して、AIを導入してヘイトスピーチ防止と未成年保護で対策を施しており、またその効果を検証しながら改善しているらしいですが、Facebookは内部告発をされては会社名をMetaに改名して、メタバースの開発を急ぐばかり。
そんな会社の作るReactを使いたいのですか?
React、本当に導入したい?
これまで、まるでReactをバッシングするような内容を書いてきましたが、Reactは画期的なものだったと筆者は思っています。部品という概念を広めたのはReactです。そこからWeb Componentsができた訳ですし、フロントエンド開発が面白くもなりました。
それに、プロジェクトでフレームワークを使うこと自体はとても大切だと思います。我々エンジニアはみんな、必ずしも正しいとは限らない、クセがあります。フレームワークをプロジェクトで使うことで、書き方の約束事がいくつかできるからエンジニアをまとめるのにはとても有効です。Linter・フォーマッターと同様です。
どのフレームワークも、採用する時に、それが廃れてしまった時のことを考えるべきだと思います。つまり、技術的な負債を考慮に入れるべきだということです。
Litだったら、ほぼWeb Components APIをそのまま使っているので、技術的な負債はほぼない。
Vueは、DOMに近い、HTML5に近いので違うフレームワークにポートしやすいかと。
Reactは?Reactの技術的な負債を考えてください。
こいつはとてもなく独特だし、Reactが廃れた時には確実に0から書き直しになる。
とはいいえ、最近はとても人気で、採用の広報でも「Reactを使って開発していますぜ!」というアピール、会社を粋に見せることができるので、完全には否定できません。
世の中には、流行りというものがあります。プログラミング界隈にももちろんあります。
Reactは、流行りです。
その流行りを鵜呑みにせず、よく考えて使っていこう、というのが筆者の真に言いたいことです。
筆者は、自分が書いていることが絶対だと思うほど、思い上がっていないのです。半年前は「React最高!」とあちらこちらで宣伝していたのです。なので、ここで書いたことは、あくまでも意見だと思ってください。
2022/10/21振り返ってみる
最近、筆者はWeb ComponentsとAngular(廃盤になった古いAngularJSではなく!)に深く潜っているような状況で、オブジェクト指向によるフロントエンド設計の良さに気づかされています。
Angularはとてもよいフレームワークですが、パッケージサイズが大きいことは否応なく否定できません。
しかし、大型のアプリケーションを構築する際、書き方をある程度統一させるAngular一択だと思います。エンタープライズレベルのアプリケーション、安定性が必須なアプリケーションはやはりAngularのような堅実なフレームワークが向いています。
パフォーマンスと相互性、将来性を重視するとWeb Componentsもまた圧勝です。
それでも、ほとんどの会社の求人を見ると、どのようなスキルを求めているのでしょうか?
React。必ずReactは求人に載っているのです。 お金をかけてもいいくらい。
実際にまだJQueryを使っていることがバレバレな会社でもなぜReactを求人に載せているようです。
なぜか?
応募が集まるからだそうです。
筆者はこないだ、知り合いの採用担当に話を聞いたら、Reactを求人に載せる応募が圧倒的に増えるらしいです。上記でも筆者は多少触れましたが、銘柄あてでReactを採用していることもあれば、その銘柄の力を借りて採用目的でReactを使うことがあると知りました。
どれほどかというと、あのデジタル庁までもこの風潮に合わせてReactを求人に載せているのです。これを見た筆者は驚きました。国が作るソフトウェアにReactが入るというのでレベルが知れてしまいます。すぐに出したくて品質はさほど重要でないアプリケーションならともかく、安定性、セキュリティ、パフォーマンスが重要であろう、長年にメンテナンスしていかないといけないであろうアプリケーションにしょっちゅう変わるReactを使いますか?