###JSX の本質を理解する
『JSX』という名前は『JavaScript』と『XML』の組み合わせ でできてる。JSX は XML ライクな記述ができるようにした ECMAScript 2015 に対する構文拡張
JSX の構文は、本質的には ReactElement オブジェクトを生成するための式
変数に代入したり、狭義のオブジェクトのプロパティ値にしたり、関数の引数や 戻り値にしたりもできる
###なぜ React は見た目とロジックを混在させるのか
機能単位で分割された独立性の高いパ ーツを組み合わせることでアプリケーションを構築しようというのが React の開発思想
そのパーツがコンポーネントという
React はコンポーネント自身が、 自身の描画に必要な処理を自分でやり、レンダリングもコンポーネントごとに個別で行われる
そしてそれらはコンポーネント単位で並列に非同期で実行される
私たちが作ろうとしてるのは、ひとつの URL リクエストに対してひとつの静的な HTML ページ を返すだけの単純なアプリじゃないからね。複数の外部 API との並列的な非同期通信、取得データ のキャッシュやローカルストレージへの永続化、ユーザーの操作によって即座に変化する UI の状態 管理、ときにはカメラや GPS といったデバイスへのアクセスまでをも備えた、インタラクティブで レスポンス性の高いアプリなんだよ。比べるべくはモバイルアプリやデスクトップアプリであって、 サーバサイド Web アプリケーションの延長で考えるべきではないの
###なぜ React はテンプレートを使わないのか
・Templates separate technologies, not concerns. (テンプレートは技術を分離するのであって、関心を分離しない)
・Display logic and markup are inevitably tightly coupled. (見た目のロジックとマークアップは必然的に分かちがたく結びついてる)
・HTML テンプレート派 AngularJS、Angular、Vue.js、Ember.js、Aurelia、Svelte など
・JS ファースト派 React、Preact、Mithril、Cycle.js、hyperapp など
HTMLテンプレート派は Web アプリケーションのことを『動的な Web ページ』だと考える。
JS ファースト派は Web アプリケーションもデスク トップやモバイルアプリと同じ普通のアプリケーションであり、ただブラウザがプラットフォーム になっているだけだと考える。
Vue.js も Angular も npm のダウンロード数は React よりずっと少ないのに、Google トレンドの検索数では長い間 React を上回ってたのは、その決まりごとが多すぎて開発者がしょっちゅう検索しないとコードが書けないから
###なぜ React は View をタグツリーで表現するのか
手数は増えるかもしれないけど囲みタグ形式は視認性において優れてる
####React 用の各種レンダラー
・React DOM 18 ...... HTML DOM(公式標準パッケージ)
・react-test-renderer19 ......JavaScriptオブジェクト(公式標準パッケージ)
・ReactART20 ......HTML5CanvasやSVGなどのベクターグラフィック(公式標準パッケージ)
・React Native 21 ...... iOS および Android のネイティブアプリケーション
・React Native for Windows + macOS 22 ...... Windows および macOS のネイティブアプリケ ーション
・React 360 23 ...... ブラウザ上で動く VR アプリケーション
・React-pdf24 ......PDFドキュメント
・react-three-fiber25 ......WebGLによる3Dグラフィック
・ReactFigma26 ......Figmaプラグイン
・React Sketch.app 27 ...... Sketch ファイル
つまり React とは Web にとどまらずアプリケーションやドキュメントを包括的に抽象化するも のであり、それを各プラットフォームに合わせて具現化するためのものがレンダラーなのね
##5-2. JSX の書き方
###JSX の基本的な文法
tsconfig.json で jsx オプションを react に設定している場合、JSX の記述は React.createElement(...) のように 変換される。だから createElement メソッドの上位モジュールである React がインポートされてな いと変換後、参照エラーになってしまう
見えなくても JSX では React が使われてるわけですもんね。だから JSX の構文を 書く前には React のインポートが必要
ファイルの拡張子は .tsx だけど、これは JSX を JavaScript じゃなく TypeScript ベー スにするときの拡張子
{} の中は、あくまで書けるのは式、つまり値を返す表現だけ
if とか for とかの値を返 さない制御文は書けない
任意の条件によってレンダリングするものを分けたい
const n = Math.floor(Math.random() * 10); // 0 〜 9 の整数を生成 const threshold = 5;
return (
<div>
{n > threshold && <p>`n` is larger than {threshold}</p>}
<p>`n` is {n % 2 === 0 ? 'even' : 'odd'}</p>
</div>
);
JSX では繰り返し処理もこんな感じ
const list = ['Patty', 'Rolley', 'Bobby'];
return (
<ul>
{list.map((name) => (
<li>Hello, {name}!</li>
))}
</ul>
);
JSX におけるコメントの書き方
{
3 > 1 && 'foo' // インラインコメント
}
{/*
複数行に
渡るコメント
*/}
JSX はあくまで JavaScript で HTML ではないので、 のような HTML 形式のコ メントは書けない
{} による式埋め込みの中で // コメント や /* コメント */ といった JavaScript のコメント記法を使う
複数の要素が含まれるときにトップレベルがひとつの要素じゃないといけない
HTML にレンダリングされたとき意味のないノード階層が余分にできてしまう
『フラグメント(Fragment)』を使うことで、不要なノードを追加することなく複数の要 素をまとめて扱うことができるようになる
<>>で囲う
###JSX とコンポーネントの関係
import React from 'react';
import Greets from './components/Greets';
const App: React.FunctionComponent = () => (
<div className="App">
<Greets name="Patty" times={4}>
<span role="img"aria-label="rabbit"> </span>
</Greets>
…
</div> );
export default App;
props とは『Properties(プロパティ)』の略で、
コンポーネントを関数として考えたとき、その引数に相当するもの
基本的にはコンポーネントが呼ばれるときに外から与えられる読み取り専用の変数グループをオブジェクトにまとめたも
import React from 'react';
type Props = { name: string; times?: number };
const Greets: React.FunctionComponent<Props> = (props) => {
const { name, times = 1, children } = props;
return (
<>
{[...Array(times)].map((_) => (
<p>Hello, {name}! {children}</p>
))}
</>
);
};
export default Greets;
Greets を関数コンポーネントとして型定義するため、React.FunctionComponents
インターフェー スを適用してる
このジェネリクスになってる P が props の型になるのね。この例では Props という型エイリアスで定義してる
この name と times が Greets 関数に props として渡される
して times が 省略されたときのために、分割代入で値を取りだすときデフォルト値に 1 を設定してる
最後の children は React.createElement() の第 3 引数に相当するもの
JSX においては属性値ではなく子要素として記述され、呼ばれた側のコンポーネントでは暗黙の props として渡されるようになってる
ここでは が children として設定されてる
JSX 構文における属性値としての props の渡し方だけど、通常は times={4} のように {} による式埋め込みで値を渡す
ただ値が文字列の場合は name="patty" のようにクォーテーションで 囲む形式によって渡すこともできる
また HTML エスケープされた文字列を props として渡すと受 け取ったコンポーネント側で元の文字列に復元される
JSX はテンプレートのように見えるけど、あくまで ReactElement オブジ ェクトを生成するためのシンタックスシュガー
###React の組み込みコンポーネント
React のコンポーネントには、ユーザー定義コンポーネントと組み込みコンポーネントの 2 種類がある
ユーザーが自前のコンポーネントを定義するときには命名規則があり、コン ポーネントの名前を必ず大文字から始めないといけない
JSX では小文字から始まる名前の タグ記述は、すべて組み込みコンポーネントだと解釈される
組み込みコンポーネント用のタグとして登録されているのは現在のところ、HTML 要素と SVG 要素の合計 175 個になってる
HTML だとブラウザは属性名に対して大文字と小文字を区別しないケース ・インセンシティブだけど、JSX は普通の JavaScript だから変数名は当然ケース・センシティブになる
ただしこの命名規則にも例外があって、aria-* と data-* 属性だけは HTML と同じケバブケースが適用されてる
Web アクセシビリティの標準を定めた規格があって、aria- で始まる HTML 属性がいくつも定義されてるのよ。主に視覚障害者用の読み上げブラウザのために意味づけられたもの
data-* はカスタムデータ属性といって、HTML5 の仕様で追加された、開発者がオリジナルの属性を作ることができるもの
React の組み込みコンポーネントの props と標準 HTML 要素の属性とではいくつか挙動が異なる点がある
まず JavaScript の文字ケースの挙動によるものの他に、JavaScript の予約語とかぶってしまったせいで名前自体を変更せざるをえなかったものがある。それがこの 2 つ
・class → className
・for → htmlFor
HTML での挙動と異なり、その値が Boolean になってる属性が次の 3 つ
・checked
・disabled
・selected
React では と も value 属性が持てるようになってるのが HTML と異なる
<form>
<textarea value="Fixed Text" />
<select value="uranus">
<option value="saturn">Saturn</option>
<option value="uranus">Uranus</option> {/*selected*/}
<option value="neptune">Neptune</option>
<option value="pluto">Pluto</option>
</select>
</form>
はそもそも値 を持てないんでしたよね。それが子要素の option と同じ value を設定すると、その要素が選択された状態になる
HTML には存在しないけど組み込みコンポーネントだけが持つ属性を 2 つ紹介
まず ref はコンポーネントを実際にレンダリングされるリアル DOM へ結びつける参照のため の属性
const TextInput: React.FunctionComponent = () => {
const inputRef = React.useRef<HTMLInputElement>(null);
const handleClick = (): void => {
if (inputRef.current) inputRef.current.focus();
};
return (
<div>
<input type="text" ref={inputRef} />
<input type="button" value="Focus" onClick={handleClick}/>
</div> );
};
ref 属性の中に任意のオブジェクトを設定しておくと、組み込みコンポーネントがリアル DOM としてレンダリングされた際に、渡されたオブジェクトの .current プロパティにそのリアル DOM への参照値を入れてくれる
だから handleClick() 関数の中で .focus() メソッドが実行できて る実体は、レンダリングされた HTML DOM の HTMLInputElement オブジェクト になる
とりあえずリアル DOM への参照が ref という属性でできる
key 属性は React が再レンダリングのための差分検出を効率的に行うのに必要とするもの
・JSX は ReactElement オブジェクトを生成するシンタックスシュガーで、構文 のベースはあくまで JavaScript である
・HTML の気分で書いた
とかも、実際に は React の組み込みコンポーネントに変換される
・属性値や子要素はコンポーネントに props という関数に対する引数のようなものとして渡される