👁

Reactの基本

この章では、Reactの基本について概要を解説し、ハンズオン形式で実際に動作させながら学習します。これにより、JSXによるUI記述・コンポーネント・propsによるデータの受け渡し・useStateによる状態管理など、Reactで画面を作る基本が身につきます。

1. 本章の概要

1.1 本章の目的

これまで扱ってきたJavaScriptやTypeScriptだけでWebアプリケーションの画面を作ろうとすると、状態と表示を同期させる処理を自分で書き続けなければならず、画面の規模が大きくなるほど扱いが難しくなります。この課題を解決するために、状態から見た画面の姿を宣言的に記述できるライブラリやフレームワークとして、ReactVue.js などが登場しました。

なお、Reactにルーティングやレンダリング方式・ビルド設定などをまとめて備え、より効率よくWebアプリケーションを作れるようにしたフレームワークとして Next.js があり、次の章で扱います。Next.js は React をベースにしているため、本章では先に React の基本的な考え方と書き方を、独立した環境(Vite)で一通り扱います。

1.2 ハンズオンの流れ

最小のReactプロジェクトを立ち上げ、書いたコードがすぐにブラウザに反映される環境で、コンポーネントの作り方・データの受け渡し・状態の持たせ方といったReactの基本を、一通り動かしながら習得できるようにします。

1.3 事前準備

必要なツール

この章では、以下のツールを使用します。まだインストールしていない場合は、リンク先の手順に沿って準備をお願いします。

ツール名 関連箇所 理由
Visual Studio Code Visual Studio Codeのインストール Reactコードを記述するエディタとして使用する
Node.js Node.jsをインストールしよう Viteによる開発サーバの起動とコンパイルに使用する

2. なぜReactを使うのか

Reactの必要性を、JavaScript だけで DOM を直接書き換える書き方と比較しながら整理します。

2.1 DOM操作の課題

前章までで扱った問い合わせフォームでは、document.getElementById(...)element.textContent = ... のように、変更したい要素を1つずつ取り出して書き換える書き方をしていました。この書き方は、画面が単純なうちは分かりやすい一方で、規模が大きくなると次のような課題が出てきます。

  • 状態が変わるたびに、関連するすべての要素を漏れなく書き換える必要がある
  • どの状態のときに画面がどう表示されるかが、コードの複数箇所に散らばる
  • 画面の要素が増えるほど、書き換え処理が指数的に複雑になる

たとえば「カート内の商品数を変更したら、ヘッダのバッジ・カート一覧・合計金額の3箇所を同時に更新する」といった処理をDOM操作だけで書くと、次のようになります(このコードは動作確認のためではなく、書きぶりを示すための例です)。

function updateCartQuantity(itemId, newQuantity) {
  // 1. カート一覧の該当行を書き換え
  document.querySelector(`#cart-item-${itemId} .quantity`).textContent = newQuantity;

  // 2. ヘッダのバッジも書き換え
  document.querySelector("#header .cart-badge").textContent = calcTotalItems();

  // 3. 合計金額の表示も書き換え
  document.querySelector("#total-price").textContent = calcTotalPrice();
}

3箇所の書き換えを、すべてこの関数の中で忘れずに呼ぶ必要があります。どれか1つでも書き換えを漏らすと画面と実データがずれ、カート機能や表示箇所が増えるほど「関連要素を漏れなく更新する」ためのコードが各所に散らばります。

2.2 Reactによる宣言的な書き方

Reactは、「今の状態のときに画面がどう見えるか」を関数として書けば、状態が変わったときの再描画はReact側が自動で行う、という書き方を採用しているUIライブラリです。書き手は「差分の書き換え手順」ではなく「最終形の見た目」を宣言するだけで、あとはReactが必要な最小限の要素だけを更新します。

具体的には、画面をコンポーネント(component)と呼ばれる部品に分けて、それぞれの部品が「自分の状態から見た自分の見た目」を返す関数として書きます。状態が変われば関連するコンポーネントだけが再実行され、Reactが差分を計算してDOMに反映してくれるため、書き手はDOM操作の手順を書かずに済みます。

TypeScriptとの相性もよく、コンポーネント間で受け渡すデータ(props)に型を付けて安全にデータをやり取りできます。この章ではTypeScriptを使ってReactの基本を扱います。

3. セットアップ

Reactを動かすには、.tsx ファイルをブラウザで動くJavaScriptに変換するビルドツールが必要です。ここでは、Reactの新規プロジェクトを作るときによく使われるVite(ヴィート)を使って、最小のReactプロジェクトを準備し、開発サーバでブラウザに表示できるところまでを確認します。

3.1 プロジェクトの初期化

まず、Reactを扱うための空のプロジェクトを作り、Viteによる開発サーバの起動までを行います。

任意の場所に react-practice フォルダを作成し、Visual Studio Codeの「ファイル」→「フォルダーを開く」から、作成した react-practice フォルダを開きます。以降の操作は、Visual Studio Codeのターミナルから行います。

react-practice  ← このフォルダを作成

以下のコマンドで、npmがインストールされていることを確認します。

npm --version

以下のようにnpmのバージョンが表示されれば、インストールは確認できています。

10.x.x

バージョンが表示されない場合は、Node.jsをインストールしよう を先に実施してください。

インストールが確認できたら、以下のコマンドでVite製のReactプロジェクトを、いま開いているカレントフォルダに生成します。

npm create vite@latest . -- --template react-ts

npm create vite@latest はViteの公式スキャフォールディングコマンドで、直後の . は「カレントフォルダ(いま開いている react-practice)に生成する」ことを指定し、-- --template react-ts の部分で「React + TypeScript のテンプレート」を指定しています。

実行中に対話プロンプトが順に出るので、以下のように答えます。

  • Package name: → そのまま Enter(フォルダ名の react-practice が使われます)
  • Ok to proceed? (y)y を入力して Enter
  • Which linter to use?Oxlint を選択して Enter
  • Install with npm and start now?Yes を選択して Enter

最後の Install with npm and start now?Yes と答えると、Viteがスキャフォールディング・依存パッケージのインストール・開発サーバの起動までまとめて実施します。以下のような実行結果が表示されれば、開発サーバの起動まで完了しています。

◇  Scaffolding project in /path/to/react-practice...
◇  Installing dependencies with npm...

added 27 packages, and audited 28 packages in 2s

found 0 vulnerabilities

◇  Starting dev server...

> react-practice@0.0.0 dev
> vite

  VITE v8.x.x  ready in 500 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

Visual Studio Codeのサイドバーには、以下のような構成が表示されます。

react-practice/
├── node_modules/
├── public/
├── src/
│   ├── App.css
│   ├── App.tsx
│   ├── assets/
│   ├── index.css
│   ├── main.tsx
│   └── vite-env.d.ts
├── .gitignore
├── index.html
├── package.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts

以降の節で編集するファイルは、主に src/App.tsx の1つだけです。他のファイルはViteの設定や雛形として初期状態のまま使います。

💡 ポイント
このコマンドを実行したターミナルは開発サーバに占有されたままになります。以降のコマンドを実行するときは、Visual Studio Codeで「ターミナル」→「新しいターミナル」から別のターミナルを開いてください。開発サーバを止めたい場合は、動いているターミナルで Ctrl + C を押します。

3.2 動作確認

セットアップの最後で開発サーバが起動しているので、ブラウザから表示できるかを確認します。

ブラウザで http://localhost:5173 を開くと、React と Vite のロゴを重ねたイラスト、Get started の大きな見出し、Edit src/App.tsx and save to test HMR の案内、Count is 0 の薄紫色のボタン、下部に DocumentationConnect with us のカードが並んだ、Viteのウェルカム画面が表示されます。

Count is 0 のボタンをクリックすると、Count is 1Count is 2 と数字が1ずつ増えていきます。以下は4回クリックしたあとの状態です。

クリックのたびにボタン内の数字が追随して変われば、Reactの開発サーバが正しく動作していることが動作確認できます。

⚠️ ポートが 5173 以外に切り替わる場合
別のプロセスがすでに 5173 番ポートを使っている場合、Viteは自動的に 5174・5175 など次に空いているポートを使います。ブラウザで開くURLは、ターミナルに表示されている Local: http://localhost:XXXX/ のポート番号に合わせてください。

4. コンポーネントとJSX

Reactの中心にあるのがコンポーネントという考え方と、そのコンポーネントの中身を「HTML風の記法でJavaScriptに書ける」ようにするJSXです。ここでは、最小のコンポーネントを書き、JSXの記法と変数の埋め込みを確認します。

4.1 コンポーネントの基本

Reactでは、画面を関数として書きます。関数の戻り値として画面の中身(JSX)を返すだけで、それがそのままコンポーネントになります。書き方は以下のとおりです。

export default function コンポーネント名() {
  return (
    // JSX
  );
}

次のコードは、Hello, React! と表示するだけの最小のコンポーネントを書いた例です。src/App.tsx を以下のコードに書き換えます。

export default function App() {
  return <h1>Hello, React!</h1>;
}

ブラウザで http://localhost:5173 を開くと、以下の表示に切り替わります。

Hello, React!

雛形のカウンタ画面が消え、<h1> の見出しだけが表示されれば、書き換えたコンポーネントが正しく描画されています。

コードを解説します。

export default function App() {
  return <h1>Hello, React!</h1>;
}

App という名前の関数を定義し、その戻り値として <h1>Hello, React!</h1> を返しています。関数名の頭を大文字にする(App / Header など)のがReactでのコンポーネント名の慣例です。export default された関数がそのままコンポーネントとして扱われ、Reactが自動的にHTMLに変換してブラウザに描画します。

💡 ポイント
一度開発サーバを起動していれば、以降のサンプルコードでは src/App.tsx を書き換えて保存するだけで、Viteが変更を自動的に検知してブラウザに反映してくれます。サーバを都度再起動する必要はなく、以降の節でも「ファイルを保存する → ブラウザで結果を確認する」の流れだけで進められます。開発サーバを止めたい場合はターミナルで Ctrl + C を押します。

4.2 JSXの記法

JavaScriptの関数の中に <h1>...</h1> のようなHTML風の記法が書けるのが、JSX(JavaScript XML)と呼ばれるReactの拡張構文です。ブラウザはJSXをそのままでは解釈できないため、Viteのような開発ツールが裏側でJavaScriptに変換してくれます。書き方は以下のとおりです。

return (
  <タグ名>
    <子タグ>...</子タグ>
  </タグ名>
);

複数の要素を返したいときは、必ず1つのタグで囲む必要があります。囲むタグ自体を残したくないときは <> </>フラグメント(空タグ)を使います。

次のコードは、<div> の中に見出しと段落を並べた例です。src/App.tsx を以下のコードに書き換えます。

export default function App() {
  return (
    <div>
      <h1>My Profile</h1>
      <p>Reactの学習を始めました。</p>
    </div>
  );
}

保存すると、ブラウザが自動的にリロードされ、以下の表示に切り替わります。

My Profile
Reactの学習を始めました。

見出しと本文が縦に並んで表示されれば、JSXでの複数要素の記述が動作しています。

コードを解説します。

return (
  <div>
    <h1>My Profile</h1>
    <p>Reactの学習を始めました。</p>
  </div>
);

return の後に丸括弧 () を書き、その中にJSXを並べています。複数の要素を返す場合は、必ず1つの親要素(ここでは <div>)で囲む必要があります。囲まないと「隣り合う要素は1つの親要素にまとめる必要がある」というエラーが出ます。

JSXはHTMLに似ていますが、いくつかHTMLと違うルールがあります。

観点 HTML JSX
クラス指定 class="foo" className="foo"
ラベルの for for="email" htmlFor="email"
インラインスタイル style="color: red;" style={{ color: "red" }}(後述)
属性名の書き方 小文字 キャメルケース(onclickonClick

classfor はJavaScriptの予約語と重なるため、React側では className / htmlFor で書きます。属性名がキャメルケースになるのは、JSXがJavaScriptの式として評価される都合です。

4.3 変数の埋め込み

JSXの中では、{式} のように波括弧で囲んで JavaScript の式を埋め込めます。変数を表示したり、簡単な計算結果を表示したりするときに使います。書き方は以下のとおりです。

<タグ名>{JavaScriptの式}</タグ名>

次のコードは、nameage の変数の値をJSXに埋め込む例です。src/App.tsx を以下のコードに書き換えます。

export default function App() {
  const name = "田中太郎";
  const age = 30;

  return (
    <div>
      <h1>Hello, {name}!</h1>
      <p>年齢は{age}歳です。</p>
    </div>
  );
}

保存すると、ブラウザが自動的にリロードされ、以下の表示に切り替わります。

Hello, 田中太郎!
年齢は30歳です。

{name} {age} の位置に変数の値が埋め込まれて表示されれば、JSXの変数埋め込みが動作しています。

コードを解説します。

const name = "田中太郎";
const age = 30;

コンポーネントの関数内で、通常のJavaScriptと同じように変数を宣言できます。

<h1>Hello, {name}!</h1>
<p>年齢は{age}歳です。</p>

JSXの中の {name}{age} の部分がJavaScriptの式として評価され、その結果がテキストとして埋め込まれます。{} の中には変数だけでなく、{age + 1} のような計算式や {name.toUpperCase()} のようなメソッド呼び出しも書けます。

4.4 インラインスタイルの記法

JSXでスタイルをインラインで指定したいときは、style 属性にオブジェクトを渡します。ここが波括弧が二重になるポイントで、外側の {} は「JSXの中でJavaScriptの式を書く」ため、内側の {} は「JavaScriptのオブジェクトリテラル」のためです。書き方は以下のとおりです。

<タグ名 style={{ プロパティ名: "値", プロパティ名: "値" }}>...</タグ名>

次のコードは、見出しの文字色と背景色をインラインスタイルで指定する例です。src/App.tsx を以下のコードに書き換えます。

export default function App() {
  return (
    <div>
      <h1 style={{ color: "white", backgroundColor: "steelblue", padding: "0.5rem" }}>
        スタイル付きの見出し
      </h1>
    </div>
  );
}

保存すると、ブラウザが自動的にリロードされ、以下のように背景色付きの見出しが表示されます。

(青背景・白文字の「スタイル付きの見出し」がパディング付きで表示される)

指定した色と余白が反映された見出しが表示されれば、インラインスタイルの記述が動作しています。

コードを解説します。

<h1 style={{ color: "white", backgroundColor: "steelblue", padding: "0.5rem" }}>

外側の {} はJSX内でJavaScript式を書くための波括弧で、内側の {} はスタイルオブジェクトを直接記述するための波括弧です。二重に見えますが、意味が違う2つの波括弧が並んでいるだけです。CSSプロパティ名は background-color ではなく backgroundColor のようにキャメルケースで書きます。

5. props(プロパティ)

コンポーネントを部品として使えるようにするには、外から値を渡せるようにする必要があります。この「外から渡す値」を Reactでは props(プロパティの略)と呼びます。書き方は以下のとおりです。

function コンポーネント名({ プロパティ名1, プロパティ名2 }: { プロパティ名1: 型; プロパティ名2: 型 }) {
  return (
    // props を使ったJSX
  );
}

コンポーネントの引数として、propsをオブジェクトで受け取ります。TypeScriptを使う場合は、そのオブジェクトの型も一緒に書きます。

5.1 propsによる値の受け渡し

次のコードは、nameage をpropsで受け取る UserProfile コンポーネントを作り、App から2回呼び出す例です。src/App.tsx を以下のコードに書き換えます。

function UserProfile({ name, age }: { name: string; age: number }) {
  return (
    <div>
      <h2>{name}</h2>
      <p>年齢: {age}歳</p>
    </div>
  );
}

export default function App() {
  return (
    <div>
      <UserProfile name="田中太郎" age={30} />
      <UserProfile name="鈴木花子" age={25} />
    </div>
  );
}

保存すると、ブラウザが自動的にリロードされ、以下の表示に切り替わります。

田中太郎
年齢: 30歳
鈴木花子
年齢: 25歳

2人分のプロフィールがそれぞれのpropsに応じて表示されれば、propsによる値の受け渡しが動作しています。

コードを解説します。

function UserProfile({ name, age }: { name: string; age: number }) {

UserProfile コンポーネントの引数として、nameage を持つオブジェクトを分割代入で受け取っています。型として { name: string; age: number } を指定することで、呼び出し側が違う型の値を渡そうとしたときにTypeScriptがコンパイル時にエラーを検出してくれます。

<UserProfile name="田中太郎" age={30} />
<UserProfile name="鈴木花子" age={25} />

UserProfile を呼び出すときに、name="田中太郎" のようにHTMLの属性と同じ形でpropsを渡します。文字列はダブルクォートで、数値や変数はJSX式({})で囲んで渡す点に注意します。

5.2 interfaceによるprops型の切り出し

propsが増えてくると、引数の型部分が長くなって読みづらくなります。前章のTypeScriptで扱った interface を使って、propsの型を別途宣言しておくのが一般的です。書き方は以下のとおりです。

interface コンポーネント名Props {
  プロパティ名: 型;
  // ...
}

function コンポーネント名({ プロパティ名 }: コンポーネント名Props) {
  // 処理
}

次のコードは、先ほどの UserProfile を interfaceで型付けし直した例です。src/App.tsx を以下のコードに書き換えます。

interface UserProfileProps {
  name: string;
  age: number;
  email?: string;
}

function UserProfile({ name, age, email }: UserProfileProps) {
  return (
    <div>
      <h2>{name}</h2>
      <p>年齢: {age}歳</p>
      {email && <p>メール: {email}</p>}
    </div>
  );
}

export default function App() {
  return (
    <div>
      <UserProfile name="田中太郎" age={30} email="tanaka@example.com" />
      <UserProfile name="鈴木花子" age={25} />
    </div>
  );
}

保存すると、ブラウザが自動的にリロードされ、以下の表示に切り替わります。

田中太郎
年齢: 30歳
メール: tanaka@example.com
鈴木花子
年齢: 25歳

email が指定された1人目にはメール行が表示され、email を渡していない2人目には表示されなければ、オプショナルなpropsが動作しています。

コードを解説します。

interface UserProfileProps {
  name: string;
  age: number;
  email?: string;
}

propsの型を UserProfileProps として切り出しています。email?: string? はオプショナルプロパティで、渡さなくてもよいpropsを表します。コンポーネント名に Props を付けた命名がReactでの慣例です。

{email && <p>メール: {email}</p>}

JSX内では条件付き描画も {} の中の式で書けます。email && <p>...</p> は「email が空でなければ <p> を描画する」というJavaScriptの短絡評価をそのまま利用した書き方です。

5.3 childrenによる子要素の受け取り

親コンポーネントから渡される「タグの間に挟まれた子要素」は、children という特別なpropsで受け取れます。共通の枠(カード・モーダルなど)を作って、中身を呼び出し側から差し込みたい場面で使います。書き方は以下のとおりです。

function コンポーネント名({ children }: { children: React.ReactNode }) {
  return (
    // 外枠のJSX。{children} を差し込みたい位置に置く
  );
}

次のコードは、共通の枠を持つ Card コンポーネントを作り、その中に別の内容を差し込む例です。src/App.tsx を以下のコードに書き換えます。

function Card({ children }: { children: React.ReactNode }) {
  return (
    <div style={{ border: "1px solid #ddd", padding: "1rem", margin: "0.5rem 0" }}>
      {children}
    </div>
  );
}

export default function App() {
  return (
    <div>
      <Card>
        <h2>お知らせ</h2>
        <p>本日のメンテナンス予定はありません。</p>
      </Card>
      <Card>
        <h2>更新履歴</h2>
        <p>v1.2.0 をリリースしました。</p>
      </Card>
    </div>
  );
}

保存すると、ブラウザが自動的にリロードされ、以下のように枠付きのカードが2つ表示されます。

(枠付きカード内に「お知らせ」の見出しと本文)
(枠付きカード内に「更新履歴」の見出しと本文)

灰色の枠と余白を持つカードが2つ並び、それぞれ違う中身が表示されていれば、children による子要素の受け取りが動作しています。

コードを解説します。

function Card({ children }: { children: React.ReactNode }) {

children は特別な名前のpropsで、呼び出し側で <Card>...</Card> のタグに挟まれた要素がすべてここに渡されます。型は React.ReactNode で、JSX要素・文字列・数値・配列などJSXとして描画できるあらゆる値を受け入れます。

<Card>
  <h2>お知らせ</h2>
  <p>本日のメンテナンス予定はありません。</p>
</Card>

<Card>...</Card> のタグの間に書いた要素が、そのまま Card コンポーネントの children として渡されます。この仕組みにより、「外枠」と「中身」を別々のコンポーネントに切り出して組み合わせられます。

6. 状態管理(useState)

Webアプリケーションでは、「ボタンを押した回数を数える」「入力欄に打ち込まれた文字を保持する」「モーダルウィンドウの開閉を切り替える」など、時間経過やユーザ操作に応じて変化する値をコンポーネントが持ちたい場面がよくあります。この「コンポーネントが自分の中に持ち、変わったときに画面に反映してほしい値」を、Reactでは状態(state)と呼びます。

状態を持たせるには、通常のJavaScriptのように変数を宣言して代入するだけでは不十分で、Reactが変更を検知して画面を再描画できる形にする必要があります。そのために使うのが React Hooks の1つである useState です。書き方は以下のとおりです。

const [状態変数, セッター関数] = useState(初期値);

useState は「現在の状態」と「状態を更新する関数」の2つを配列で返すので、分割代入で受け取ります。セッター関数を呼ぶと状態が更新され、Reactがコンポーネントを再実行して画面を更新してくれます。

6.1 状態を持たない場合の問題

まず、状態を使わずに変数だけでボタンの動きを書こうとするとどうなるかを確認します。src/App.tsx を以下のコードに書き換えます。

export default function App() {
  let count = 0;

  return (
    <div>
      <p>現在の値: {count}</p>
      <button onClick={() => (count = count + 1)}>+1する</button>
    </div>
  );
}

保存してブラウザで「+1する」ボタンを何度クリックしても、画面の数字は 0 のまま変わりません。

現在の値: 0

count 変数は増えていますが、Reactは「状態が変わった」ことを検知できず、画面が再描画されないためです。関数コンポーネントは、状態が変わったときだけ再実行されて画面を更新します。ふつうのローカル変数を書き換えても、Reactはそれを追いかけません。

6.2 useStateで状態を持たせる

同じカウンタを、useState を使って書き直します。src/App.tsx を以下のコードに書き換えます。

import { useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>現在の値: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1する</button>
    </div>
  );
}

保存してブラウザで「+1する」ボタンをクリックするたびに、現在の値: の数字が1ずつ増えていきます。以下は、初期状態(0)・1回クリックした状態(1)・3回クリックした状態(3)の3枚です。

現在の値: 3

ボタンをクリックするたびに 現在の値 の数字が追随して増えていけば、useState による状態管理が動作しています。

コードを解説します。

import { useState } from "react";

useState は React が提供する関数(Hook)なので、react から import して使います。Hooksはコンポーネントの関数内でしか呼び出せないというルールがあります。

const [count, setCount] = useState(0);

useState(0) は「初期値 0 の状態」を作り、[現在の値, 更新関数] の配列を返します。分割代入で count(現在の値)と setCount(更新関数)を受け取ります。変数名は自由に付けられますが、「状態名」と「set + 状態名」のペアにするのが慣例です。

<button onClick={() => setCount(count + 1)}>+1する</button>

onClick に渡した関数がクリック時に実行されます。setCount(count + 1) を呼ぶと、count の値が更新され、Reactが App コンポーネントを再実行して画面を更新します。この「セッター関数を呼ぶ → コンポーネントが再実行される → 画面が更新される」という流れが、Reactの状態管理の中核です。

📝 Hooks の呼び出しルール
useState などのHooksは、コンポーネント関数のトップレベルでしか呼び出せません。if 文や for ループの中で条件付きに呼び出すことは禁止されています。理由は、Reactが「何番目に呼ばれた useState はこの状態」という順序で状態を管理しているためです。詳細は Rules of Hooks(React公式ドキュメント) に記載があります。

6.3 入力フォームでの状態管理

状態管理の応用として、入力フォームの値を状態として保持する例を見ます。フォームの入力値をReactに管理させることで、送信ボタンの活性・非活性の制御や、入力バリデーションの結果表示が書きやすくなります。src/App.tsx を以下のコードに書き換えます。

import { useState } from "react";

export default function App() {
  const [name, setName] = useState("");

  return (
    <div>
      <label>
        名前:
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
      </label>
      <p>入力中の名前: {name}</p>
    </div>
  );
}

保存してブラウザの入力欄に文字を打つと、入力欄の値と段落の表示が同期します。以下は、入力前の状態と テスト太郎 と入力した状態の2枚です。

入力中の名前: テスト太郎

入力するたびに 入力中の名前: の後の文字がリアルタイムで更新されれば、onChangeuseState が正しく連携しています。

コードを解説します。

const [name, setName] = useState("");

空文字を初期値として、name に現在の入力値を持たせます。

<input
  type="text"
  value={name}
  onChange={(e) => setName(e.target.value)}
/>

value={name} で入力欄の表示を状態と同期させ、onChange で入力があるたびに setName を呼んで状態を更新します。この「入力値をReactの状態として管理する」書き方を、Reactでは制御されたコンポーネント(controlled component)と呼びます。

7. まとめ

この章では、Reactの基本を学びつつ、実際にコードでコンポーネントの記述・props・状態管理を確かめました。

  • Reactは、「今の状態から画面がどう見えるか」を関数として書くことで、状態の変化に応じた画面の更新をReact自身に任せられるUIライブラリである
  • Viteを使うことで、.tsx ファイルを書けるReactの最小プロジェクトをコマンド1本で作成できる
  • コンポーネントは関数として定義し、JSXで戻り値としてHTML風のUIを記述できる
  • JSXでは class の代わりに classNamestyle にはオブジェクトを渡すなど、HTMLとの細かな違いがある
  • propsによって、コンポーネントの外から値を受け取り、interface で型付けして安全にデータを受け渡せる
  • children により、コンポーネントの中身を呼び出し側から差し込める共通の枠を作れる
  • useState により、コンポーネントに状態を持たせ、状態の変化に応じて画面を自動で再描画できる

次の章では、Reactを土台にしたフレームワークである Next.js の基本を学びつつ、実際にプロジェクトを作成して動作を体験します。

この教材は役に立ちましたか?

いいねをたくさんいただけると、制作者の励みになり、より多くのセクションが作れるようになります。

感想を一言(任意)

いただいたコメントは次の制作のヒントになります。ぜひお気軽にご投稿ください。

このコメントは他の受講生には公開されません。DevOps Camp運営が、教材改善のために確認します。

0 / 2000