UIパーツのためのJavaScriptライブラリである「React」の基礎について、チュートリアルも含めて紹介します。

JavaScriptとHTMLに慣れている人向けの解説ですが、他のプログラミング言語を使ってきた人にも理解できるように考えてみましょう。


React とは

Reactは、FacebookがOSSとして公開しているUIパーツのためのライブラリです。

複雑なUIをコンポーネントと呼ばれる小さく独立した部品から構築できます。


Reactを使うメリット

すっかり定番となったReactの魅力は、やはり高速で動く点です。

しかもAPIも数えるほどしかなくシンプルなので、初心者にも使いやすいでしょう。

書き方もパーツごとになるため、一度作っておけば他の場面で再び利用できたり、バグを修正しやすかったりもします。

Reactさえ覚えておけば、後はReact Nativeを使ってスマートフォンアプリまで作成可能です。


Reactの注意点

シンプルで使いやすいReactですが、公式のドキュメントは現在のところ英語しかありません。

またWindowsと相性がかなり悪いため、開発環境の構築が大変という点も注意です。その代わり一度構築すればあとが楽になります。


Hello WorldでReactを使ってみる

まずは、Hello Worldを書いてみるとこのような構文になります。

  1. ReactDOM.render(
  2. <h1>Hello, World!</h1>,
  3. document.getElementById(‘root’)
  4. );

ブラウザに表示されるものは、定番の「Hell,World!」です。


JSXの導入

UIの見た目をコーディングするために、ReactではJSXと呼ばれるJavaScript構文を使用することが多いです。

JSXを使用することは必須ではありませんが、公式サイトにて勧められています。


JSXにJavaScript関数を埋め込む

下記の例ではformatName(user)というfirrstnameとlastNameを結合するJavaScript関数の結果を<h1>要素の中に埋め込んでいます。

  1. function formatName(user) {
  2. return user.firstName + ‘ ‘ + user.lastName;
  3. }
  4. const user = {
  5. firstName: ‘Harper’,
  6. lastName: ‘Perez’
  7. };
  8. const element = (
  9. <h1>
  10. Hello, {formatName(user)}!
  11. </h1>
  12. );
  13. ReactDOM.render(
  14. element,
  15. document.getElementById(‘root’)
  16. );

ウィンドウには「Hello, Harper Perez!」と表示されます。


JSXで子要素を指定する

JSXの子要素を持つことができるタグです。

  1. const element = (
  2. <div>
  3. <h1>Hello!</h1>
  4. <h2>Good to see you here.</h2>
  5. </div>
  6. );

そうすると「Hello! Good to see you here.」と表示されます。


要素

要素とは

Reactの最小単位の構成ブロックは要素と呼ばれます。

  • const element = <h1>Hello, world</h1>;


要素をDOMとして描画する

React要素をルートDOMノードにレンダリングするには、ReactDOM.render()に渡しましょう。

  1. const element = <h1>Hello, world</h1>;
  2. ReactDOM.render(element, document.getElementById(‘root’));


コンポーネント

Reactはコンポーネントと呼ばれるUI部品で構成されます。概念的にはJavaScriptの関数と似ているものです。

”props”(プロパティの意味)と呼ばれる入力を受け取り、React要素を返しましょう。

詳細なAPIリファレンスはこちらです。

React.Component: https://ja.reactjs.org/docs/react-component.html


関数コンポーネント

最もシンプルにコンポーネントを定義する方法は、JavaScriptの関数を書くことです。

  1. function Welcome(props) {
  2. return <h1>Hello, {props.name}</h1>;
  3. }

これはpropsというオブジェクトを引数として受け取り、React要素を返すJavaScriptの関数です。

このようなコンポーネントのことを関数コンポーネント(function component)と呼びます。


クラスコンポーネント

ES6クラスを使用したコンポーネントを定義することも可能です。

  1. class Welcome extends React.Component {
  2. render() {
  3. return <h1>Hello, {this.props.name}</h1>;
  4. }
  5. }


コンポーネントを組み合わせる

コンポーネントは他のコンポーネントを参照できます。

下記の例では、Appコンポーネントがwelcomeコンポーネントを3回参照している場合です。

  1. function Welcome(props) {
  2. return <h1>Hello, {props.name}</h1>;
  3. }
  4. function App() {
  5. return (
  6. <div>
  7. <Welcome name=”Sara” />
  8. <Welcome name=”Cahal” />
  9. <Welcome name=”Edite” />
  10. </div>
  11. );
  12. }
  13. ReactDOM.render(
  14. <App />,
  15. document.getElementById(‘root’)
  16. );

そうすると「Hello, Sara」「Hello, Cahal」「Hello, Edite」の3文が表示される筈です。


stateとライフサイクル

Reactコンポーネントにおいて、コンポーネントを再利用可能かつカプセル化されたものにする方法を説明しましょう。

詳細なAPIリファレンスも先に紹介した「React.Component」のサイトにもありますので参考にして下さい。


stateを使用したクラスコンポーネント

秒刻みでの時計を表示するプログラムを例として考えます。

下記のようにReact.Componentを継承したクラスを使用することができます。

  1. class Clock extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {date: new Date()};
  5. }
  6. render() {
  7. return (
  8. <div>
  9. <h1>Hello, world!</h1>
  10. <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
  11. </div>
  12. );
  13. }
  14. }
  15. ReactDOM.render(
  16. <Clock />,
  17. document.getElementById(‘root’)
  18. );

「Hell,World! It is…」と表示され、「It is」の後に表示される秒の部分が変更されます。


ライフサイクルメソッドの追加

通常のアプリケーションは、多くのコンポーネントを有するものです。

そのためコンポーネントが破棄された場合に、そのコンポーネントが占有していたリソースを開放することが重要となります。

最初にコンポーネントが描画されるのがマウントです。

コンポーネントが生成したDOMが削除(解放)された状態のことをアンマウントと呼びます。

先ほどのプログラミングに、マウントとアンマウントの際の考慮を追加したのが下記のプログラムです。

  1. class Clock extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {date: new Date()};
  5. }
  6. componentDidMount() {
  7. this.timerID = setInterval(
  8. () => this.tick(),
  9. 1000
  10. );
  11. }
  12. componentWillUnmount() {
  13. clearInterval(this.timerID);
  14. }
  15. tick() {
  16. this.setState({
  17. date: new Date()
  18. });
  19. }
  20. render() {
  21. return (
  22. <div>
  23. <h1>Hello, world!</h1>
  24. <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
  25. </div>
  26. );
  27. }
  28. }
  29. ReactDOM.render(
  30. <Clock />,
  31. document.getElementById(‘root’)
  32. );

componentDidMount() メソッドは、出力が DOM にレンダーされた後に実行されます。

componentWillUnmount()メソッドはコンポーネントが解放される直前に実行されるものです。


処理の仕組み

上記のプログラムでは何が起きているのかを整理しましょう。

まず、ReactDOM.render()に<Clock />が渡されるとClockコンポーネントのコンストラクタが呼び出されます。

Clockは現在時刻を呼び出すために、現在時刻を含んだオブジェクト{date: new Date()}でthis.state初期化します。

このthis.stateが更新されているのです。

次にClockコンポーネントのrender()メソッドが呼び出されます。これにより、Reactは画面に何を表現するかを認識するのです。

そののちに、ReactはDOMをClockのレンダー出力と一致するよう更新します。

Clockの出力がDOMに挿入されるとReactはcomponentDidMount()メソッドを呼び出すのです。

componentDidMount()の中で、Clockコンポーネントは毎秒ごとにコンポーネントのtick()メソッドを呼び出します。

タイマーを設定するようにブラウザに要求するのです。

次にブラウザは、tick()メソッドを毎秒ごとに呼び出します。

その中でClockコンポーネントは、現在時刻を含んだオブジェクトを引数としてsetState()を呼び出す。

これによりUIの更新をスケジュールするのです。

setState()が呼ばれたらReactはstateが変わったことを認識し、render()メソッドを再度呼び出して、画面上に何を表示すべきかを知ります。

今回は、render()メソッド内のthis.state.dateは同じものにはなりません。

レンダリングされる出力には新しく更新された時間が含まれています。それに従って、ReactはDOMを更新するのです。

この後にClockコンポーネントがDOMから削除。

解放される直前に、ReactはcomponentWillUnmount()メソッドを呼び出し、これによりタイマーが停止します。


イベント処理

イベント処理の文法的な特徴

Reactのイベント処理はDOM要素のイベント処理と非常に似ていますが、いくつか文法的な違いがあります。

まずReactのイベント名は小文字ではなく、キャメルケースです(例:onClick)。

JSXではイベントハンドラとして、関数を渡します。

  1. <button onClick={activateLasers}>
  2. Activate Lasers
  3. </button>

Reactでは、falseを返してもデフォルトの動作を抑止することができません

そのため、明示的にpreventDefault を呼び出す必要があります。

  1. function ActionLink() {
  2. function handleClick(e) {
  3. e.preventDefault();
  4. console.log(‘The link was clicked.’);
  5. }
  6. return (
  7. <a href=”#” onClick={handleClick}>
  8. Click me
  9. </a>
  10. );
  11. }


アロー関数

コールバック内でアロー関数を使用することができます。

  1. class LoggingButton extends React.Component {
  2. handleClick() {
  3. console.log(‘this is:’, this);
  4. }
  5. render() {
  6. // This syntax ensures `this` is bound within handleClick
  7. return (
  8. <button onClick={(e) => this.handleClick(e)}>
  9. Click me
  10. </button>
  11. );
  12. }
  13. }


イベントハンドラに引数を渡す

ループ内で、イベントハンドラに追加のパラメータを渡す方法です。

例えば、idというIDがある場合、以下のどちらでも動作します。

上側がアロー関数、下側はFunction.prototype.bindが使われているので確認しておきましょう。

  1. <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
  2. <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
  3. }


React公式サイトのチュートリアルを解説

Reactの公式サイトのチュートリアルについて

React公式サイトにて、導入のチュートリアルがあります。

Reactの導入チュートリアル:https://ja.reactjs.org/tutorial/tutorial.html

ちなみに紹介したチュートリアルでは、〇×ゲームの作り方を学ぶことが可能です。


チュートリアルの準備

公式サイトには「ブラウザでコードを開く」方法と「ローカル開発環境」で実施する方法が紹介されています。

ここではブラウザの方をご紹介しましょう。

codepenというサイトにリンクがはられています。

codepen公式サイト(全文英文): https://codepen.io/

Node.jsのインストールやnpmでの操作が問題ない人は「ローカル開発環境」でもよいかもしれません。

上記公式サイトを参考にして設定を行い、srcフォルダ内のindex.jsファイルを編集してチュートリアルを行ってください。


スターターコードの中身を確認する

それでは、ブラウザでスターターコードを開いてください。

スターターコード:https://codepen.io/gaearon/pen/oWWQNa?editors=0010

このスターターコードに機能を追加していくのがチュートリアルです。

JSという欄に書かれているコードを見ると3つのコンポーネントがあります。

  • Square(正方形のマス目)
  • Board(盤面)
  • Game


Props経由でデータを渡す

最初は、BoardコンポーネントからSquareコンポーネントにデータを渡す機能を追加しましょう。

公式サイトでは、チュートリアルでコードを変換する際にはコピペではなく、手入力での変更を推奨しています。

手が動きを覚えて、理解が進むからです。

BoardのrenderSquareメソッド内で、propsとしてvalueという名前の値をSquareに渡すようにコードを変更します。

  1. class Board extends React.Component {
  2. renderSquare(i) {
  3. return <Square value={i} />;
  4. }
  5. }

続いて、Squareのrenderメソッドで、{/* TODO */} を {this.props.value} に書き換えて、渡された値を表示。

  1. class Square extends React.Component {
  2. render() {
  3. return (
  4. <button className=”square”>
  5. </button>
  6. );
  7. }
  8. }

変更前は何も番号が表示されていませんが、変更後には盤面にそれぞれ番号が表示されます

これで親であるBoardコンポーネントから、Squareコンポーネントに「propを渡す」ことができたことになるのです。


インタラクティブなコンポーネントを作る

次は、マス目がクリックされた場合に“X”と表示される機能を追加します。

まずは、Squareコンポーネントのrender()関数にあるボタンタグを以下のように変更しましょう。

変更後に、マス目をクリックするとアラートが表示されます。

  1. class Square extends React.Component {
  2. render() {
  3. return (
  4. <button className=”square” onClick={() => alert(‘click’)}>
  5. {this.props.value}
  6. </button>
  7. );
  8. }
  9. }

次は、Squareコンポーネントに自分がクリックされたことを「覚え」させて、“X”マークでマスを埋めるようにしましょう。

コンストラクタでthis.stateを設定することで、Reactコンポーネントは状態を持つことができるようになります。

現在のSquareの状態をthis.stateに保存し、マス目がクリックされたら、変更するようにしてください。

コンストラクタの追加とrenderメソッドの変更を行います。

  1. class Square extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {
  5. value: null,
  6. };
  7. }
  8. render() {
  9. return (
  10. <button
  11. className=”square”
  12. onClick={() => this.setState({value: ‘X’})}
  13. >
  14. {this.state.value}
  15. </button>
  16. );
  17. }
  18. }

Squareのrenderメソッドの変更点は以下の点です。

  • <button>タグ内のthis.props.valueをthis.state.valueに変更する
  • onClick={…}というイベントハンドラをonClick={() => this.setState({value: ‘X’})}に変更する
  • 読みやすくするために、classNameとonClickの両プロパティをそれぞれ独立した行にする

Squareのrenderメソッド内に書かれたonClickハンドラ内で、this.setStateを呼び出しましょう。

Reactに<button>がクリックされたら、再レンダーするように伝えることができます。

データ更新の後、このSquareのthis.state.valuは’X’になってますので、画面上にXと表示。

この時点では、どのマス目をクリックしてもXが出てくるはずです。


ゲームを完成させる

これまでのチュートリアルで、Reactの基本的な機能は体験できたのではないでしょうか。

後は、「盤面にXと〇を交互に置けるようにすること」「どちらのプレイヤーが勝利したか判定できるようにすること」が必要となります。

続きは、Reactの公式サイトの「ゲームを完成させる」をご参照ください。


Developer Tools

ChromeとFireFox用にReact Developer Tools拡張機能があります。

ブラウザ開発ツールでReactのコンポーネントツリーを調べることが可能です。

またここではReactコンポーネントのpropsとstateも確認できます。

チュートリアルの完成形を動かした実際の画面では、Squareコンポーネントのpropsの値も確認可能です。


jQueryと比較したメリット

仮想DOMによる高速なレンダリング

Reactは仮想DOMと呼ばれるページ上の更新が必要な部分だけを再描画する「差分検出処理」を行っています。

そのためレンダリングが高速です。


React NativeによるiOS/Androidアプリ開発

Reactをモバイルアプリ開発向けにした「React Native」があり、Reactを学ぶと同じ要領で開発をすることができます。

ただしReactでWeb向けに開発したものが、そのままiOS/Androidで動作するわけではありません。


ReactとjQueryの違い

最近はReactさえあればjQueryはいらないという話もありますが、ReactとjQueryは得意分野が違います

jQueryはサイトの中のちょっとした細かい部品を作ったり、余分な部分を削って調整したりするのが得意です。

簡単にいうなら、彫刻刀のようなものでしょう。

対してReactは設計図を読み込んで、部品を自動的に精製するプリンターのようなもの。

このように考えれば、根本的に違うことが分かるのではないでしょうか。

向いていることやできることはかなり違います。

スムーズな開発を行うには、両方とも使えるようになる方が良いでしょう。


まとめ

Reactの基礎を解説しました。

あまりプログラミングに慣れていない人にとっては難しかったかもしれません。

しかし一度覚えれば、先に解説したようなゲームを作ることができます。

使い方を習得することで、様々な機能をつけることができます。少しずつ覚えて、UI開発に生かしていきましょう。