2019年12月18日スポンサーリンク業務で開発しているプロジェクトでReactを入れることになりまして、そのためのインプットとしてReactの公式チュートリアルを行いました。今回はチュートリアルで学んだことを整理しつつ1つ1つの工程ごとにまとめていこうと思います。Reactの知識が何もない初心者の方でもわかってもらえるように、押さえておくべき部分が出てきた時にその都度解説を挟むようにしています。追加課題おわりにReactチュートリアルとはそもそもReactはFacebookが開発したもので、公式ページにチュートリアルがあります。こちらにある内容と同じものを今回作成していきました。英語で書かれていますが、こちらでは日本語でまとめていこうと思います。開発環境Reactの環境はすごく簡単に作成することができて、やり方に関してはこちらの記事を参考にしてください。create-react-appコマンドでReactの環境構築を一瞬で作成する今回業務で開発しているプロジェクトにReactを入れてみることになりました。それにあたって、学習のためにReactのサンプルプログラム...今回みたいにチュートリアルだけ手軽にやってみたい、というような場合には環境構築をしなくてもhtmlファイルに直接書いていくのでも大丈夫です。</script></body></html>このようにして書いていけば、ブラウザ上でちゃんと表示されると思います。ファイル分割をしようと思うとうまくいかないので、分割してしっかり書きたい場合は開発環境を整えていきましょう。作成するもの作成するのはこのようなものです。誰でもやってことがある「○×ゲーム」です。公式ページではtic-tac-toeゲーム(三目並べ)と呼ばれています。上に現状のプレイヤーが誰か、勝負がついた場合に勝者が通知される右に履歴がでてきてボタンを押したらその時点に遡ることができる。いうようなものを作成していきます。本家の完成版がこちらにのっています。https://github.com/fkt1993/react-sample-app今回作成したものはこちらのリポジトリにまとめましたのでそちらでも確認ができます。初期設定ある程度出来上がったコードが用意してあって、それをいじっていくことになります。HTML,cssの部分は完成されているのでjavascriptの部分をひたすらいじっていきます。本家の最初のコードはこちらです。https://github.com/fkt1993/react-sample-appでも、コミットを遡れば最初の状態のものがあるので参照することができます。これ以降の手順を1つずつコミットしてあるので段階ごとに遡れるようにしています。null;}このようになっています。簡単に説明していきます。document.getElementById('container'));こう書くことによってcontainerにGameコンポーネントでレンダリングされたDOMが入ります。コンポーネントというのはクラスで書かれていて、renderメソッドを定義すれば先程のというように書けばこの部分にrenderメソッドで返されるDOMがレンダリングします。あとで説明しますが、stateとして値を保持することもできます。次にGameコンポーネントを見ていきましょう。/>の部分にはrenderメソッド内に書かれているDOMが返されます。見てみるとこの中身は見慣れたものかと思いきや少し違う部分があるかと思います。これはjsxといってこれもfacebookが開発した独自タグの技術です。普段DOMをjavascriptで定義するとき文字列の連結を駆使してやっているとわりと見にくかったりします。jsxの表記だとhtmlに近い書き方なので見やすいですがいくつかお作法があります。その1つがclassNameです。classがjavascriptの予約後なのでhtmlのクラスを定義する際にjsxの中ではclassNameと記述します。ひとつ、変数を埋め込む際には{}で囲むだけで大丈夫です。これによって変数を埋め込む場合でも見やすいです。*/}とあるのは{}の中身はコメントなので後々書き換えて表示するようにしていく部分です。/>というのがあるのでBoardコンポーネントをみていきます。}}Boardコンポーネントはこの様になっています。ここでは3×3のマスをレンダリングしています。renderメソッド内を見ていくと、{this.renderSquare(0)}というようになっています。先程も説明しましたがjsxで、変数を埋め込む場合の表記は{}で囲むだけです。ここでは、renderメソッド内でstatusを定義してそれを{status}と書いて埋め込んでいます。Boardコンポーネント内にrenderSquareというメソッドが定義されていてそれを呼び出す際には、this.(メソッド名)で呼び出すことができます。引数も渡すことができます(やりかたは後述)。/>とあるのでSquareコンポーネントを見ていきます。これはマス1つをレンダリングするものですね。}}このようになっています。ここは先程までの説明と同様ですね。これで全体像が見えました。Game,Board,Squareの3つのコンポーネントで構成されていて、しっかりとわけられていて、1つ1つがすっきりしています。これがReactのメリットの1つです。することで機能が増えてきても役割が分かれているのでカオスになりにくいです。チュートリアルpropsを通してデータを渡すまず手始めにマスの中に何かしらを表示していきます。現状このように枠しか無いのをこのように数字を順番に表示させていきます。手順の流れとしてはBoardがSquareに対してn番と表示されたマスを表示するという命令を出すようにします。BoardからSquareに引数を渡すようにします。}}このように記述することで引数を渡すことができます。}}受け取る側はこのようにすることで値を受け取ることができます。これでマスの中に数字が表示されるはずです。stateで状態をもたせる次に、このままでは無いも変化がないのでなにもないマスをクリックしたときにXが表示されるようにします。その場合2つのポイントがあります。現在のマスの状態をどこかに保持するクリックしたときのどうするかを実装するです。状態を保持できるようにしていきます。Componentではstateを使って状態を保持できると先程書きました。それを今回実装していきます。1つ1つのマスで自分自身のマスに何が表示されているかを保持するようにしていきます。Squareコンポーネントを書き換えていきます。}}stateを実装する場合constructorを定義してこのように書いていきます。constructorでは明示的にsuperメソッドを呼び出す必要があります。先程this.props.valueとしていた部分をthis.state.valueとすることでstateの値を表示するようにできます。次にクリックしたときの挙動を実装していきます。{this.props.value}</button>というように記述することで定義できます。これはJavaScript(ES2015)のアローファンクション構文を使用しています。今回はマスをクリックするとアラートが表示されます。今回はマスをクリックした際にstateのvalueをnullからXに変更したいです。'X'})というようにsetStateを呼べば値が変更されます。{this.props.value}</button>というようにします。実行してみると、このようになっているはずです。状態を上に渡すさて、stateをもたせることができましたが、この先に○と×を交互にでるようにしたり、勝敗が決まったかどうかを判定したりする機能を作る際に、現状のように各マスがstateを保持している状態では管理がし辛いです。毎回各マスに問い合わせるというやりかたもできなくはないですが、理解しづらい破綻しやすいコードになってしまうのでReactではそうさせないようにしています。結論としては、上の階層であるBoardコンポーネントに状態をもたせるようにしたほうがいいです。Reactでは親子のコンポーネントでデータをやり取りする場合には親に状態をもたせるようにするのがセオリーです。いうことでBoardコンポーネントにstateをセットしていきます。この際9マスの情報を集めるので9つの要素をもった配列で状態を表すようにします。加えて、マスがクリックされたときにstateも変化するようにしないといけません。この場合、onclickで実際に呼ぶ場所は子(Square)、値を保持しているのが親(Board)ということになるのでどのようにすればいいかというと、呼ばれたら状態を変更するという処理を親(Board)で定義して、それを子(Square)に渡すということをします。Boardはこのようになります。}}Squareは以下のようになります。}}これで変更が完了です。機能的には特に変わってはいないです。squares});}このような部分がありました。クリックしたときにsquaresの対応する要素を変更するメソッドですが、squaresに変更を加えるのではなくsquares配列をコピーしています。変更してしまえばすぐ終わりな作業をわざわざこのようにしているのは意味があります。そもそもプログラミングにおいて変数を極力使わずに定数のみを使ったほうがいいというセオリーがあります。いうのは変更を許可すると思わぬところで値が書き換わっている可能性があるのでバグを生みやすいのとコードが複雑になって理解しにくなるからです。ここで、Reactでは、stateの変更を検知してstateを使用している各要素に変更を伝えて、値を受け取り、要素単位で考えたときに受け取った値が変更があれば再レンダリングをするという流れです。このために最小限の部分しか変更しないので描画が軽いという特徴があります。変更が許可されたオブジェクトの変更を検知する場合には、全体のオブジェクトツリーをスキャンしてそれぞれの変数と値を比較する必要があります。これは複雑かつ時間がかかります。変更が禁止されているオブジェクトでは参照されているオブジェクトが以前のものと同じかどうかを判定するだけでいいので変更の検知がしやすいです。したがってReactの特徴を最大限いかすために普遍性が重要になるわけです。関数コンポーネントSquareコンポーネントはstateを持たなくなったのでconstructorは不要になったので削除します。その場合Squareコンポーネントはrenderメソッドのみからなるコンポーネントとなります。componentsとして書くことができます。);}Squareコンポーネントはこのように書くことができます。この場合this.propsと今までしてたのが、propsとなるのに注意です。現状だとXしか表示されないので○とXが交代になるようにしていきます。stateに次のプレイヤーがどちらになるかを保持するものを追加します。}}このようになったかと思います。勝敗を判定する次は勝負がついてきたときの表示を実装していきます。勝敗がついたかどうかを判定する関数自体はもともと用意してくれていて、calculateWinner(squares)が下の部分に実装されているかと思います。reactでサーバーを建てて実行している場合はwarningで今までcalculateWinnerを使ってないよっていうのがでててかと思いますがここから使用します。Boardコンポーネントを変更していきます。勝敗がついているかどうかを判定して、ついていたら勝者を表示するようにします。加えて、勝敗がついたときにそれ以降マスをおしても何も起こらないようにするのと、これまですでに埋まっているマスをクリックしても上書きできてしまっていたのですでに埋まっているマスをクリックしても何も起こらないようにします。}}これでちゃんと動くものが完成しました!このようになっているかと思います。履歴を記録するゲームは完成しましたが機能を拡張していきます。各動作がどのような状態だったかわかるようにいつでも過去の状態に戻れるようにしていきます。どのようにしていくかというと、すべてのマスの状態を配列として格納していましたが、毎回動作のたびに新しい配列を作成していたのを利用します。historyという配列を作成して、その1つの要素に今までのsquaresを格納するようにします。することで各動作ごとの状態を保持することができます。各動作のリストをどこで表示させるかを考えていきます。Boardコンポーネントでは3×3のボードを作るのに専念させたほうがいいのでよりトップレベルのGameコンポーネントにその役割を任せます。した場合に、序盤でSquareコンポーネントからBoardコンポーネントに状態を引き上げたように、今回もBoardコンポーネントからGameコンポーネントに状態を引き上げていかないといけません。Boardはこのようにconstructorを削除して、stateを参照していた部分をpropsに変更します。statusを表示していた部分はGameがその役割を担うので削除します。}}Gameコンポーネントは以下のようになります。}}いままでrenderメソッドしかなかったのをすべてここに集約するようになっています。役割を移しただけなのでまだ機能としては変わっていません。ここから履歴を表示するようにします。}}このように変更します。Reactで複数のアイテムをレンダリングする際の一般的な方法は、配列のデータをmapすることです。map関数でDOMを返すようにしていきます。これを実行するとこのようにwarningが出てきてしまいます。これにはある理由があります。KeyReactではレンダリングを最小限にするために変更されたものしか再レンダリングをしないような仕組みになっています。先程のwarningの原因は、リストを再レンダリングを最小限にするための仕組みがどうなっているかを考えてみると見えてきます。このようなリストがあったとします。left</li>それがこのように変更したとします。left</li>人間の目で見た際には順番が変わって、1つ要素が増えて、中身の値も一部が変わっているというようにわかりますが、Reactはこれだけでは今のようなことを認識してくれるわけではありません。そこでReactではリストの各要素にkeyプロパティを指定することで順番が変わったとしても新しく追加されたとしても、中身の値を変更する必要があるかどうか認識することができます。認識するためにはkeyはユニークである必要があるので今回は、alexa,ben,claudiaをkeyとするのがよいです。上から順番に1からふっていくというようなやり方は順番が変わったとしても上から順番に1から振られてしまうので適切ではありません。DBのオブジェクトと一致する場合はDBのIDをkeyとして使うのが適切です。このようにReactではアイテムのリストをレンダリングする際に常にリスト内の各アイテムの情報を記録しているので、要素数が多かったとしても再レンダリングする必要があるアイテムだけ再レンダリングされます。マルバツゲームの実装に戻ると、このwarningを解消するためには今までの話を踏まえるとkeyを要素に追加すればいいわけです。);});これでwarningが解消されたかと思います。現状だとボタンを押してもjumpToメソッドを定義していないので実装していきます。}}これですべて完成です!完成品はこの様になっています。コード類はhttps://github.com/fkt1993/react-sample-appここで管理もしているので良かったら参考にしてください。追加課題チュートリアルの内容は一通り完成しましたが、一番最後に以下のように追加課題が課せられています。公式のチュートリアルでは追加課題は課題が課されるだけで実際の答えのようなものは存在しません。こちらの記事で、追加課題をやってみたものをまとめてみたので、もし興味があれば見てみてください。【入門】Reactチュートリアルをやりながら実践入門〜追加課題編〜Reactの学習用に開発元のFacebookが公式のチュートリアルを提供してくれています。そのチュートリアルの内容の一番最後に追加課題が出されていて、今回はその追加課題をやってみたものを初心者でもわかるようにコードも載せつつ解説していきます。...おわりに今回React.jsのチュートリアルを行いました。内容を見ていくと単なるチュートリアルだけではなく概念など細かい部分にも言及されていたので、理解のために非常に助けになりました。当サイトはエックスサーバーで運営しています。方はこちらの記事を参考にしてください。仮想通貨1【windows】FFmpegをインストールする手順2FFmpegで動画変換!各OSごとのインストール方法と使い方まとめ3【簡単】MacにHomebrewをインストールする方法と基本的な使い方4HomebrewでMacにFFmpegをインストールする方法と使い方5macOSにXcodeをインストールしよう6BootCampでMacにWindows10をインストールする7〜初心者でもわかるswift入門〜基本文法からiOSアプリを開発するまで8【swift入門】apiを叩いてTableViewに表示させる9【Xcode】ファイル追加削除するときの注意10【入門】Reactチュートリアルをやりながら実践入門お問い合わせこちらからお願いいたします。