はじめに
<Hello />
のようなコンポーネントは最終的にどうやってブラウザに描画されるの?とふと思ったので、備忘録的にまとめていきます。
つまり、React
とJSX
がどのように連携して仮想DOM
を構築し、最終的に実際のDOM
を更新するかをまとめます。
コンポーネントの定義
React
では、コンポーネントは再利用可能なUIの一部を表現します。一般的には個々のファイルに定義され、必要に応じて他のファイルからインポートされます。
export function Hello() {
return <h1>Hello, world!</h1>;
}
JSXとReact要素の作成
上記の書き方はJSX
と呼ばれ、React.createElement()
のシンタックスシュガー = 糖衣構文です。
React
要素を作成するには、本来このようなAPIを呼ぶ必要があります。
それぞれtype
,props
,children
という引数を取り、React要素を作成します。
const element = React.createElement(
'h1', // type
null, // props
'Hello, world!' // children
);
一方で、JSX
ではより直感的にHTML
に近い書き方でReact要素を作成することができます。
export function Hello() {
return <h1>Hello, world!</h1>;
}
シンタックスシュガーではありますが、JSX
からReact
要素を作成するには、Babel
などのトランスパイラを使用してJSX
を通常のJavaScript
に変換する必要があります。これは、ブラウザやNode.js
はJSX
を直接理解することができないからです。この変換過程で、JSX
内のタグはReact.createElement()
の呼び出しに変換されます。
<Hello />
は、トランスパイラによって次のようにトランスパイルされます。
React.createElement(Hello)
これは、React.createElement
関数が、指定された型(この場合はHello
)とプロパティで新しいReact
要素を作成することと同じ意味です。
仮想DOMへの追加と差分評価
このReact
要素は、仮想DOM
に追加され、最終的に実際のDOM
にレンダリングされます。
仮想DOMに追加するには、ReactDOM.render
関数を用いることができ、以下の様な引数を取ります。
ReactDOM.render(
//1.React要素,
//2.DOM要素
)
ReactDOM.render()
が呼び出されると、React
はメモリ内に仮想DOMツリー
を作成し、各コンポーネントの状態を管理します。
React
は実際のDOM
との結果の差異を計算することで、ブラウザに表示されていて「実際に表示変更が必要となるコンポーネントのみ」を効率的にレンダリングします。
export function Hello() {
return <h1>Hello, world!</h1>;
}
import { Hello } from './Hello';
function App() {
return <Hello />;
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script src="./App.js"></script>
</body>
</html>
まとめ
-
JSX
はReact.createElement
のシンタックスシュガー -
JSX
はReact.createElement
に変換するにはBabel
などのトランスパイラ
が必要 -
ReactDOM.render
が呼び出され、実際のブラウザとの差分をReact
が評価することで、差分のコンポーネントのみレンダリングされる