チュートリアル:React の導入
この記事は古くなっており、今後更新されません。新しい React 日本語ドキュメントである ja.react.dev をご利用ください。
新しくなったチュートリアルでは最新の React の使い方がライブサンプル付きで学べます。
このチュートリアルは React の事前知識ゼロでも読み進められます。
チュートリアルを始める前に
このチュートリアルでは小さなゲームを作成します。自分はゲームを作りたいのではないから、と飛ばしたくなるかもしれませんが、是非目を通してみてください。このチュートリアルで学ぶ技法はどのような React のアプリにおいても基本的なものであり、マスターすることで React への深い理解が得られます。
ヒント
このチュートリアルは実際に手を動かして学びたい人向けに構成されています。コンセプトを順番に学んでいきたい人は一段階ずつ学べるガイドを参照してください。このチュートリアルとガイドは互いに相補的なものです。
このチュートリアルは複数のセクションに分割されています。
- チュートリアルの準備:以下のチュートリアルを進めるにあたっての開始地点です。
- 概要:コンポーネントや props、state といった基礎概念について学びます。
- ゲームを完成させる:React での開発における非常によくある技法について学びます。
- タイムトラベル機能の追加:React 独自の利点について深い洞察が得られます。
このチュートリアルから価値を得るために全セクションを一度に終わらせる必要はありません。セクション 1 つや 2 つ分でも構いませんので、できるところまで進めましょう。
これから作るもの
このチュートリアルでは、インタラクティブな三目並べゲーム (tic-tac-toe) の作り方をお見せします。
最終的な結果をここで確認することができます:最終結果。まだコードが理解できなくても、あるいはよく知らない構文があっても、心配は要りません。このチュートリアルの目的は、React とその構文について学ぶお手伝いをすることです。
チュートリアルを進める前に三目並べゲームで遊んでみることをお勧めします。いくつか機能がありますが、ひとつには、盤面の右側に番号付きリストがあることに気づかれるでしょう。このリストにはゲーム内で起きたすべての着手 (move) のリストが表示され、ゲームが進むにつれて更新されていきます。
どんな物か分かったら三目並べゲームを閉じて構いません。もっと小さな雛形から始めましょう。次のステップはゲームの構築ができるようにするための環境のセットアップ作業です。
前提知識
HTML と JavaScript に多少慣れていることを想定していますが、他のプログラミング言語を使ってきた人でも進めていくことはできるはずです。また、関数、オブジェクト、配列、あるいは(相対的には重要ではありませんが)クラスといったプログラミングにおける概念について、馴染みがあることを想定しています。
JavaScript を復習する必要がある場合は、このガイドを読むことをお勧めします。また ES6 という JavaScript の最近のバージョンからいくつかの機能を使用していることにも注意してください。このチュートリアルでは、アロー関数、クラス、let および const ステートメントを使用しています。Babel REPL を使って ES6 のコードがどのようにコンパイルされるのか確認することができます。
チュートリアルの準備
このチュートリアルを最後まで進めるための方法が 2 種類あります。ブラウザでコードを書くか、マシン上にローカルな開発環境をセットアップするかのどちらかです。
オプション 1: ブラウザでコードを書く
始めるのに一番手っ取り早い方法です!
まず、このスターターコードを新しいタブで開いてください。空の三目並べの盤面と React のコードが表示されるはずです。このチュートリアルではこのコードを編集していくことになります。
次のオプションはスキップして、直接概要へと進んで React の全体像を学びましょう。
オプション 2: ローカル開発環境
これは完全にオプションであり、このチュートリアルを進めるのに必須ではありません!
オプション:好きなテキストエディタを使ってローカルでチュートリアルを進める方法
このセットアップでは作業は増えますが、好きなテキストエディタを使ってチュートリアルを進めることができます。以下のステップに従ってください。
- 最新の Node.js がインストールされていることを確かめる。
- Create React App のインストールガイドに従って新しいプロジェクトを作成する。
npx create-react-app my-app- 新しく作ったプロジェクトの
src/内にあるファイルをすべて削除する
補足:
srcフォルダ自体をまるごと消すのではなく、中にあるソースファイルを削除してください。この次のステップで、デフォルトのソースファイルをこのプロジェクト用の例に置き換えます。
cd my-app
cd src
# If you're using a Mac or Linux:
rm -f *
# Or, if you're on Windows:
del *
# Then, switch back to the project folder
cd ..src/フォルダ内にindex.cssという名前のファイルを作り、ここの CSS コードを記入する。src/フォルダ内にindex.jsという名前のファイルを作り、ここの JS コードを記入する。src/フォルダ内のindex.jsファイルの先頭に以下の 3 行のコードを加える。
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';これでプロジェクトフォルダ内で npm start を実行し、ブラウザで http://localhost:3000 を開くと、空の三目並べの盤面が表示されるはずです。
ここにある指示に従って、エディタ上でシンタックスハイライティングを設定することをお勧めします。
助けて、ハマった!
もし問題にはまったら、コミュニティーによるサポート情報をチェックしてみてください。特に Reactiflux Chat は迅速なヘルプが得られます。良い回答が得られなかった場合や問題が解決しない場合は、issue を作成して下さったら、私たちがお手伝いします。
概要
準備が完了したので、React の概要を学びましょう!
React とは?
React はユーザインターフェイスを構築するための、宣言型で効率的で柔軟な JavaScript ライブラリです。複雑な UI を、「コンポーネント」と呼ばれる小さく独立した部品から組み立てることができます。
React にはいくつか異なる種類のコンポーネントがあるのですが、ここでは React.Component のサブクラスから始めましょう:
class ShoppingList extends React.Component {
render() {
return (
<div className="shopping-list">
<h1>Shopping List for {this.props.name}</h1>
<ul>
<li>Instagram</li>
<li>WhatsApp</li>
<li>Oculus</li>
</ul>
</div>
);
}
}
// Example usage: <ShoppingList name="Mark" />この妙な XML のようなタグについてはすぐ後で説明します。コンポーネントは、React に何を描画したいかを伝えます。データが変更されると、React はコンポーネントを効率よく更新して再レンダーします。
ここで ShoppingList は React コンポーネントクラス、もしくは React コンポーネント型です。コンポーネントは props(“properties” の略)と呼ばれるパラメータを受け取り、render メソッドを通じて、表示するビューの階層構造を返します。
render メソッドが返すのはあなたが画面上に表示したいものの説明書きです。React はその説明書きを受け取って画面に描画します。具体的には、render は、描画すべきものの軽量な記述形式である React 要素というものを返します。たいていの React 開発者は、これらの構造を簡単に記述できる “JSX” と呼ばれる構文を使用しています。<div /> という構文は、ビルド時に React.createElement('div') に変換されます。上記の例は以下のコードと同等です:
return React.createElement('div', {className: 'shopping-list'},
React.createElement('h1', /* ... h1 children ... */),
React.createElement('ul', /* ... ul children ... */)
);興味があれば、createElement() は API リファレンスでより詳細に説明されていますが、このチュートリアルでは直接この関数を使用することはありません。代わりに JSX を使い続けます。
JSX では JavaScript のすべての能力を使うことができます。どのような JavaScript の式も JSX 内で中括弧に囲んで記入することができます。各 React 要素は、変数に格納したりプログラム内で受け渡ししたりできる、JavaScript のオブジェクトです。
上記の ShoppingList コンポーネントは <div /> や <li /> といった組み込みの DOM コンポーネントのみをレンダーしていますが、自分で書いたカスタム React コンポーネントを組み合わせることも可能です。例えば、<ShoppingList /> と書いてショッピングリスト全体を指し示すことができます。それぞれの React のコンポーネントはカプセル化されており独立して動作します。これにより単純なコンポーネントから複雑な UI を作成することができます。
スターターコードの中身を確認する
ブラウザでチュートリアルを進めている場合、このスターターコードを新しいタブで開いてください。ローカルでチュートリアルを進めている場合は、代わりにプロジェクトフォルダにある src/index.js を開いてください(セットアップ時にこのファイルを既に触ったはずです)。
このスターターコードが我々が作ろうとしているもののベースになります。CSS によるスタイルは既に含まれていますので、React と三目並べのプログラミングに集中できるようになっています。
コードを見てみると、3 つの React コンポーネントがあることが分かります。
- Square(正方形のマス目)
- Board(盤面)
- Game
Square(マス目)コンポーネントは 1 つの <button> をレンダーし、Board(盤面)が 9 個のマス目をレンダーしています。Game コンポーネントは盤面と、後ほど埋めることになるプレースホルダーを描画しています。この時点ではインタラクティブなコンポーネントはありません。
データを Props 経由で渡す
では手始めに、Board コンポーネントから Square コンポーネントにデータを渡してみましょう。
チュートリアルを進めるにあたって、コードをコピー・ペーストしないで、手でタイプすることをお勧めします。そうすれば手が動きを覚えるとともに、理解も進むようになるでしょう。
Board の renderSquare メソッド内で、props として value という名前の値を Square に渡すようにコードを変更します:
class Board extends React.Component {
renderSquare(i) {
return <Square value={i} />; }
}そして Square の render メソッドで、渡された値を表示するように、{/* TODO */} を {this.props.value} に書き換えます。
class Square extends React.Component {
render() {
return (
<button className="square">
{this.props.value} </button>
);
}
}変更前:
変更後:描画された出力の正方形のそれぞれに番号があるはずです。
おめでとうございます! これで親である Board コンポーネントから子である Square コンポーネントに「props を渡す」ことができました。React では、親から子へと props を渡すことで、アプリ内を情報が流れていきます。
インタラクティブなコンポーネントを作る
Square コンポーネントがクリックされた場合に “X” と表示されるようにしましょう。
まず、Square コンポーネントの render() 関数から返されているボタンタグを、以下のように変更してみましょう:
class Square extends React.Component {
render() {
return (
<button className="square" onClick={function() { console.log('click'); }}> {this.props.value}
</button>
);
}
}ここで Square をクリックすると、ブラウザの開発者コンソールに ‘click’ と表示されるはずです。
補足
タイプ量を減らして
thisの混乱しやすい挙動を回避するため、この例以降ではアロー関数構文をつかってイベントハンドラを記述します。class Square extends React.Component { render() { return ( <button className="square" onClick={() => console.log('click')}> {this.props.value} </button> ); } }
onClick={() => console.log('click')}と記載したときにonClickプロパティに渡しているのは関数であることに注意してください。React はクリックされるまでこの関数を実行しません。() =>を書くのを忘れてonClick={console.log('click')}と書いてしまうのはよくある間違いであり、こうするとコンポーネントが再レンダーされるたびにログが表示されてしまいます。
次のステップとして、Square コンポーネントに自分がクリックされたことを「覚えさせ」て、“X” マークでマスを埋めるようにさせます。コンポーネントが何かを「覚える」ためには、state というものを使います。
React コンポーネントはコンストラクタで this.state を設定することで、状態を持つことができるようになります。this.state はそれが定義されているコンポーネント内でプライベートと見なすべきものです。現在の Square の状態を this.state に保存して、マス目がクリックされた時にそれを変更するようにしましょう。
まず、クラスにコンストラクタを追加して state を初期化します:
class Square extends React.Component {
constructor(props) { super(props); this.state = { value: null, }; }
render() {
return (
<button className="square" onClick={() => console.log('click')}>
{this.props.value}
</button>
);
}
}補足
JavaScript のクラスでは、サブクラスのコンストラクタを定義する際は常に
superを呼ぶ必要があります。constructorを持つ React のクラスコンポーネントでは、すべてコンストラクタをsuper(props)の呼び出しから始めるべきです。
次に Square の render メソッドを書き換えて、クリックされた時に state の現在値を表示するようにします。
<button>タグ内のthis.props.valueをthis.state.valueに置き換える。onClick={...}というイベントハンドラをonClick={() => this.setState({value: 'X'})}に書き換える。- 読みやすくするため、
classNameとonClickの両プロパティをそれぞれ独立した行に配置する。
これらの書き換えの後、Square の render メソッドから返される <button> タグは以下のようになります。
class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
value: null,
};
}
render() {
return (
<button
className="square" onClick={() => this.setState({value: 'X'})} >
{this.state.value} </button>
);
}
}Square の render メソッド内に書かれた onClick ハンドラ内で this.setState を呼び出すことで、React に <button> がクリックされたら常に再レンダーするよう伝えることができます。データ更新のあと、この Square の this.state.value は 'X' になっていますので、盤面に X と表示されることになります。どのマス目をクリックしても X が出てくるはずです。
setState をコンポーネント内で呼び出すと、React はその内部の子コンポーネントも自動的に更新します。
Developer Tools
Chrome と Firefox 用の React Devtools 拡張機能により、ブラウザの開発ツールで React のコンポーネントツリーを調べることができます。
React DevTools を使えば React コンポーネントの props と state を確認できます。
インストールした後は、ページ上の任意の要素で右クリックして、“Inspect” をクリックして開発者向けツールを開くと、React タブ(“⚛️ Components” and “⚛️ Profiler”)が右端のタブとして表示されます。“⚛️ Components” を利用して、コンポーネントツリーを検証します。
ただし、開発者向けツールを CodePen で動作させるには追加のステップが必要です:
- ログインまたは登録してメールを認証(スパム防止に必要です)。
- “Fork” ボタンをクリック。
- “Change View” をクリックして “Debug mode” を選択。
- 新しいタブを開けば、開発者向けツール内に React タブが現れるようになっているはずです。
ゲームを完成させる
ここまでで三目並べゲームの基本的な部品が揃いました。完全に動作するゲームにするためには、盤面に “X” と “O” を交互に置けるようにすることと、どちらのプレーヤが勝利したか判定できるようにすることが必要です。
State のリフトアップ
現時点では、それぞれの Square コンポーネントがゲームの状態を保持しています。どちらが勝利したかチェックするために、9 個のマス目の値を 1 カ所で管理するようにします。
Board が各 Square に、現時点の state がどうなっているか問い合わせればよいだけでは、と思うかもしれません。React でそれをすることも可能ですが、コードが分かりにくく、より壊れやすく、リファクタリングしづらいものになるのでお勧めしません。ここでのベストの解決策はそうではなく、ゲームの状態を各 Square の代わりに親の Board コンポーネントで保持することです。Board コンポーネントはそれぞれの Square に props を渡すことで、何を表示すべきかを伝えられます。以前にそれぞれの Square に番号を表示させた時と同じです。
複数の子要素からデータを集めたい、または 2 つの子コンポーネントに互いにやりとりさせたいと思った場合は、代わりに親コンポーネント内で共有の state を宣言する必要があります。親コンポーネントは props を使うことで子に情報を返すことができます。こうすることで、子コンポーネントが兄弟同士、あるいは親との間で常に同期されるようになります。
このように state を親コンポーネントにリフトアップ (lift up) することは React コンポーネントのリファクタリングでよくあることですので、この機会に挑戦してみましょう。
Board にコンストラクタを追加し、初期 state として 9 個のマス目に対応する 9 個の null 値をセットします。
class Board extends React.Component {