LoginSignup
0
0

More than 3 years have passed since last update.

第5章 JSXでUIを表現する メモ

Last updated at Posted at 2021-05-22

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>
);

タグのすぐ下に書いてるのが if 文を代用する JSX での式表現で、&& 論理演算子によるショートサーキット評価を用いてる
その下の行で用いてるのが if-else 文の代用で、三項演算子 を用いてこのように書く
n > threshold や n % 2 === 0 といった式は true か false を返すので、JSX の中に埋め 込んでも出力には影響されない

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 という関数に対する引数のようなものとして渡される

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0