クイックスタート

React ドキュメントへようこそ!このページでは、日常的に使用する React の概念の 80% について紹介します。

以下の内容を学習します

  • コンポーネントを作成し、ネストする方法
  • マークアップとスタイルを追加する方法
  • データを表示する方法
  • 条件とリストをレンダリングする方法
  • イベントに応答し、画面を更新する方法
  • コンポーネント間でデータを共有する方法

コンポーネントの作成とネスト

React アプリは *コンポーネント* で構成されています。コンポーネントとは、独自のロジックと外観を持つ UI (ユーザーインターフェース) の一部です。コンポーネントは、ボタンのように小さなものから、ページ全体のように大きなものまであります。

React コンポーネントは、マークアップを返す JavaScript 関数です。

function MyButton() {
return (
<button>I'm a button</button>
);
}

MyButton を宣言したので、別のコンポーネントにネストできます。

export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}

<MyButton /> は大文字で始まっていることに注意してください。これが React コンポーネントであることを示しています。React コンポーネント名は常に大文字で始まる必要がありますが、HTML タグは小文字である必要があります。

結果を見てみましょう

function MyButton() {
  return (
    <button>
      I'm a button
    </button>
  );
}

export default function MyApp() {
  return (
    <div>
      <h1>Welcome to my app</h1>
      <MyButton />
    </div>
  );
}

export default キーワードは、ファイル内のメインコンポーネントを指定します。JavaScript 構文の一部に慣れていない場合は、MDNjavascript.info に優れたリファレンスがあります。

JSX によるマークアップの記述

上記のマークアップ構文は、*JSX* と呼ばれます。JSX はオプションですが、ほとんどの React プロジェクトでは、その利便性から JSX を使用しています。ローカル開発に推奨されるすべてのツールは、JSX をすぐにサポートしています。

JSX は HTML よりも厳密です。<br /> のようにタグを閉じる必要があります。また、コンポーネントは複数の JSX タグを返すことができません。<div>...</div> や空の <>...</> ラッパーのように、共通の親要素でラップする必要があります。

function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}

JSX に移植する HTML が大量にある場合は、オンラインコンバーターを使用できます。

スタイルの追加

React では、className を使用して CSS クラスを指定します。これは、HTML の class 属性と同じように機能します。

<img className="avatar" />

次に、別の CSS ファイルに CSS ルールを記述します。

/* In your CSS */
.avatar {
border-radius: 50%;
}

React は、CSS ファイルの追加方法を規定していません。最も簡単な場合は、HTML に <link> タグを追加します。ビルドツールまたはフレームワークを使用する場合は、ドキュメントを参照して、プロジェクトに CSS ファイルを追加する方法を学習してください。

データの表示

JSX を使用すると、JavaScript にマークアップを配置できます。中括弧を使用すると、JavaScript に「エスケープバック」して、コードから変数を埋め込み、ユーザーに表示できます。たとえば、これにより user.name が表示されます。

return (
<h1>
{user.name}
</h1>
);

JSX属性からJavaScriptに「エスケープ」することもできますが、引用符の代わりに中括弧を使用する必要があります。たとえば、className="avatar""avatar"という文字列をCSSクラスとして渡しますが、src={user.imageUrl}はJavaScriptのuser.imageUrl変数の値を読み取り、その値をsrc属性として渡します。

return (
<img
className="avatar"
src={user.imageUrl}
/>
);

JSX中括弧内に、たとえば文字列連結など、より複雑な式を記述することもできます。

const user = {
  name: 'Hedy Lamarr',
  imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
  imageSize: 90,
};

export default function Profile() {
  return (
    <>
      <h1>{user.name}</h1>
      <img
        className="avatar"
        src={user.imageUrl}
        alt={'Photo of ' + user.name}
        style={{
          width: user.imageSize,
          height: user.imageSize
        }}
      />
    </>
  );
}

上記の例では、style={{}}は特別な構文ではなく、style={ } JSX中括弧内の通常の{}オブジェクトです。スタイルがJavaScript変数に依存する場合、style属性を使用できます。

条件付きレンダリング

Reactには、条件を記述するための特別な構文はありません。代わりに、通常のJavaScriptコードを記述するときと同じ手法を使用します。たとえば、if文を使用して、JSXを条件付きで含めることができます。

let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);

よりコンパクトなコードを好む場合は、条件演算子?を使用できます。ifとは異なり、JSX内で機能します。

<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>

else分岐が必要ない場合は、より短い論理&&構文を使用することもできます。

<div>
{isLoggedIn && <AdminPanel />}
</div>

これらのすべてのアプローチは、属性を条件付きで指定する場合にも機能します。これらのJavaScript構文のいくつかに慣れていない場合は、常にif...elseを使用することから始めることができます。

リストのレンダリング

コンポーネントのリストをレンダリングするには、forループ配列のmap()関数などのJavaScript機能に依存します。

たとえば、製品の配列があるとします。

const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];

コンポーネント内で、map()関数を使用して、製品の配列を<li>アイテムの配列に変換します。

const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);

return (
<ul>{listItems}</ul>
);

<li>key属性があることに注目してください。リストの各アイテムについて、そのアイテムを兄弟の中で一意に識別する文字列または数値を渡す必要があります。通常、キーはデータベースIDなどのデータから取得する必要があります。Reactは、後でアイテムを挿入、削除、または並べ替えた場合に何が起こったかを把握するためにキーを使用します。

const products = [
  { title: 'Cabbage', isFruit: false, id: 1 },
  { title: 'Garlic', isFruit: false, id: 2 },
  { title: 'Apple', isFruit: true, id: 3 },
];

export default function ShoppingList() {
  const listItems = products.map(product =>
    <li
      key={product.id}
      style={{
        color: product.isFruit ? 'magenta' : 'darkgreen'
      }}
    >
      {product.title}
    </li>
  );

  return (
    <ul>{listItems}</ul>
  );
}

イベントへの応答

コンポーネント内にイベントハンドラ関数を宣言することで、イベントに応答できます。

function MyButton() {
function handleClick() {
alert('You clicked me!');
}

return (
<button onClick={handleClick}>
Click me
</button>
);
}

onClick={handleClick}の最後に括弧がないことに注目してください!イベントハンドラ関数を呼び出すのではなく、渡すだけが必要です。ユーザーがボタンをクリックすると、Reactがイベントハンドラを呼び出します。

画面の更新

多くの場合、コンポーネントにいくつかの情報を「記憶」させて表示したいことがあります。たとえば、ボタンがクリックされた回数をカウントしたい場合があります。これを行うには、コンポーネントに状態を追加します。

まず、ReactからuseStateをインポートします。

import { useState } from 'react';

これで、コンポーネント内に状態変数を宣言できます。

function MyButton() {
const [count, setCount] = useState(0);
// ...

useStateからは2つのものが得られます。現在の状態(count)と、それを更新できる関数(setCount)です。任意の名前を付けることができますが、慣例として[何か、set何か]のように記述します。

ボタンが最初に表示されるとき、count0 になります。これは、0useState() に渡したためです。状態を変更したい場合は、setCount() を呼び出し、新しい値を渡します。このボタンをクリックすると、カウンターが増加します。

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

function handleClick() {
setCount(count + 1);
}

return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}

React はコンポーネント関数を再び呼び出します。このとき、count1 になります。その後、2 になります。以下同様です。

同じコンポーネントを複数回レンダリングする場合、それぞれが独自のステートを持ちます。各ボタンを個別にクリックしてください。

import { useState } from 'react';

export default function MyApp() {
  return (
    <div>
      <h1>Counters that update separately</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

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

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Clicked {count} times
    </button>
  );
}

各ボタンが自身の count ステートを「記憶」し、他のボタンに影響を与えないことに注目してください。

フックの使用

use で始まる関数は、*フック*と呼ばれます。useState は、React によって提供される組み込みフックです。他の組み込みフックは、API リファレンスにあります。既存のフックを組み合わせて、独自のフックを作成することもできます。

フックは他の関数よりも制限があります。フックはコンポーネント(または他のフック)の*最上位*でのみ呼び出すことができます。条件やループ内で useState を使用したい場合は、新しいコンポーネントを抽出してそこに配置します。

コンポーネント間でのデータの共有

前の例では、各 MyButton は独自の独立した count を持っており、各ボタンがクリックされたとき、クリックされたボタンの count のみが変更されました。

Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. Both MyButton components contain a count with value zero.
Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. Both MyButton components contain a count with value zero.

最初に、各 MyButtoncount ステートは 0 です。

The same diagram as the previous, with the count of the first child MyButton component highlighted indicating a click with the count value incremented to one. The second MyButton component still contains value zero.
The same diagram as the previous, with the count of the first child MyButton component highlighted indicating a click with the count value incremented to one. The second MyButton component still contains value zero.

最初の MyButton は、その count1 に更新します。

ただし、多くの場合、コンポーネントは*データを共有し、常に一緒に更新する*必要があります。

両方の MyButton コンポーネントが同じ count を表示し、一緒に更新するには、個々のボタンからそれらすべてを含む最も近いコンポーネントにステートを「上方に」移動する必要があります。

この例では、それは MyApp です。

Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. MyApp contains a count value of zero which is passed down to both of the MyButton components, which also show value zero.
Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. MyApp contains a count value of zero which is passed down to both of the MyButton components, which also show value zero.

最初に、MyAppcount ステートは 0 で、両方の子に渡されます。

The same diagram as the previous, with the count of the parent MyApp component highlighted indicating a click with the value incremented to one. The flow to both of the children MyButton components is also highlighted, and the count value in each child is set to one indicating the value was passed down.
The same diagram as the previous, with the count of the parent MyApp component highlighted indicating a click with the value incremented to one. The flow to both of the children MyButton components is also highlighted, and the count value in each child is set to one indicating the value was passed down.

クリックすると、MyApp はその count ステートを 1 に更新し、両方の子に渡します。

これで、どちらかのボタンをクリックすると、MyAppcount が変更され、MyButton の両方のカウントが変更されます。これをコードで表現する方法は次のとおりです。

まず、MyButton から MyApp に*ステートを移動*します。

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

function handleClick() {
setCount(count + 1);
}

return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}

function MyButton() {
// ... we're moving code from here ...
}

次に、共有クリックハンドラとともに、MyApp から各 MyButton に*ステートを渡し*ます。 <img> などの組み込みタグで以前に行ったように、JSX 中かっこを使用して MyButton に情報を渡すことができます。

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

function handleClick() {
setCount(count + 1);
}

return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}

このように渡す情報は、*props*と呼ばれます。これで、MyApp コンポーネントには、count ステートと handleClick イベントハンドラが含まれ、*両方とも props として各ボタンに渡され*ます。

最後に、親コンポーネントから渡された props を*読み取る*ように MyButton を変更します。

function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}

ボタンをクリックすると、onClick ハンドラが起動します。各ボタンの onClick prop は MyApp 内の handleClick 関数に設定されているため、その中のコードが実行されます。そのコードは setCount(count + 1) を呼び出し、count ステート変数をインクリメントします。新しい count 値は prop として各ボタンに渡されるため、すべて新しい値が表示されます。これは「ステートの持ち上げ」と呼ばれます。ステートを上に移動することで、コンポーネント間で共有しました。

import { useState } from 'react';

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

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>Counters that update together</h1>
      <MyButton count={count} onClick={handleClick} />
      <MyButton count={count} onClick={handleClick} />
    </div>
  );
}

function MyButton({ count, onClick }) {
  return (
    <button onClick={onClick}>
      Clicked {count} times
    </button>
  );
}

次のステップ

これで、React コードの書き方の基本がわかりました。

チュートリアル を確認して、実際に React で最初のミニアプリを作成してみましょう。