React 19 がリリース
React 19 がリリースされ、新たな機能や最適化が加わりました。
新バージョンの機能の前に、この記事ではベースとなっている技術について取り扱っていきます!React を学ぶ方に向けてかなり噛み砕いて説明します!
JSX ( JavaScript XML )とは?
JSX は JavaScript 内で HTML のような構文を記述できる React の拡張構文です。通常の JavaScript では UI を表現するために document.createElement()
や React.createElement()
を使用する必要があります。
通常の JavaScript:
// document.createElement() を使った場合:
document.addEventListener("DOMContentLoaded", () => {
// HTML要素を作成
const container = document.createElement("div");
container.innerHTML = `
<h1>JavaScriptでHTMLを動的に追加</h1>
<p>このHTMLはJavaScriptで生成されました。</p>
<button id="clickMe">クリックしてメッセージを表示</button>
<div id="message"></div>
`;
// 作成したHTMLをbodyに追加
document.body.appendChild(container);
// ボタンのイベントリスナーを追加
document.getElementById("clickMe").addEventListener("click", () => {
document.getElementById("message").innerText = "ボタンがクリックされました!";
});
});
または、
// React.createElement() を使った場合:
import React, { useState } from "react";
export default function App() {
const [message, setMessage] = useState("");
return React.createElement(
"div",
null,
React.createElement("h1", null, "JavaScriptでHTMLを動的に追加(React)"),
React.createElement("p", null, "このHTMLはReact.createElement()で記述されています。"),
React.createElement(
"button",
{ onClick: () => setMessage("ボタンがクリックされました!") },
"クリックしてメッセージを表示"
),
React.createElement("div", null, message)
);
}
のようになります。
JSX の構文:
import { useState } from "react";
export default function App() {
const [message, setMessage] = useState("");
return (
<div>
<h1>JavaScriptでHTMLを動的に追加(React)</h1>
<p>このHTMLはReactのJSXで記述されています。</p>
<button onClick={() => setMessage("ボタンがクリックされました!")}>
クリックしてメッセージを表示
</button>
<div>{message}</div>
</div>
);
}
JSX によってかなり見やすくなりました。
このような拡張構文は、ブラウザが直接理解するのではなく、JavaScript に変換されて実行されます。詳しくは参考に書いています。
そもそもなぜ React では JSX を使うのか?
React は Facebook (現 Meta) によって開発されたオープンソースの JavaScript ライブラリです。同社のアプリ の UI が複雑になり、メンテナンスが難しくなっていたときに社内で開発されました。
その時の目標は2つです。
- コンポーネントベース の開発手法を導入し、コードを再利用しやすくする
- 仮想DOM ( Virtual DOM ) を活用し、UIの更新を効率化する
コンポーネントベースは UI を小さな部品に分割して開発することです。こうすることによって再利用しやすく、変更、管理も楽になります。
例です。
import React, { Component } from "react";
class Button extends Component {
render() {
return <button>{this.props.text}</button>;
}
}
export default Button;
import Button from "./Button";
function App() {
return (
<div>
<h1>コンポーネントの例</h1>
<Button text="クリック" />
<Button text="送信" />
</div>
);
}
export default App;
これをReact.createElement()
で書くと記述が冗長で、可読性が低かった、という訳です。
import React from "react";
function Button({ text }) {
return React.createElement("button", null, text);
}
function App() {
return React.createElement(
"div",
null,
React.createElement(Button, { text: "クリック" }),
React.createElement(Button, { text: "送信" })
);
}
export default App;
React がオープンソースプロジェクトとなり、その後普及されるときには JSX は React の標準的な書き方となりました。
JSX は可読性が高く、HTML ライクに書くことができ、コンポーネントの記述が簡単です。また{ }
を使った JavaScript 式の統合もできるので動的にコンテンツを生成できます。
新バージョンで変わったこと
JSX がより扱いやすくなった例を紹介します。
async function
内で JSX を直接返せるようになった
例えば、以下のように短く書くことができます。
React 19:
async function App() {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
return <div>{JSON.stringify(data)}</div>;
}
export default App;
なお、これはサーバーコンポーネントのみで、クライアントコンポーネントでは従来通りです。useEffect
内で await
を使い、useState
を更新します。
"use client";
import { useState, useEffect } from "react";
function App() {
const [data, setData] = useState(null);
useEffect(() => {
async function fetchData() {
const response = await fetch("https://api.example.com/data");
const result = await response.json();
setData(result);
}
fetchData();
}, []);
return <div>{data ? JSON.stringify(data) : "Loading..."}</div>;
}
もう少し具体的に説明します。
同期的な設計とは以下のような流れです。
function App() {
return <h1>Hello, world!</h1>;
}
-
App
コンポーネントが呼び出される -
return
文で JSX を返す -
React
がその JSX を仮想DOMに変換 - 実際の DOM に反映
このとき、すべての処理は即座に完了しなければならないため、途中で非同期の処理を待つことはできません。
よってコンポーネント関数は async
にできず、また、await
を使うとエラーとなっていました。
設計の意図に立ち返ると、一度の レンダリング で UI を確定させ、不要な再計算を防ぐ ことが重要であったとも言えます。
設計思想については、宣言的 UI について参考にリンクを載せました。
React は 「現在の状態に応じた UI を宣言的に定義する」 ことを重視します。React より前からあった jQuery のように主導で DOM を更新するのではなく、データに応じた UI を返します。
まとめ
JSX は React の中核をなす構文です。これを理解してから新バージョンの更新情報を確認すると理解が深まると思います!
参考
Babelトランスパイラ
JSX は、一度 JavaScript に変換されて実行されます。React の Babel トランスパイラ を使うことで、JSX は React.createElement() の形に変換されます。
例えば、Babel によってこのように変換されます
// 変換前
const eleme
nt = <h1>Hello, world!</h1>;
// 変換後
const element = React.createElement("h1", null, "Hello, world!");
Promise
宣言的UI