@@ -31,8 +31,6 @@ redirect_from:
31
31
32
32
このチュートリアルから価値を得るために全セクションを一度に終わらせる必要はありません。セクション 1 つや 2 つ分でも構いませんので、できるところまで進めましょう。
33
33
34
- チュートリアルを進めながらコードをコピー・ペーストしても構いませんが、手でタイプすることをお勧めします。そうすれば手が動きを覚えるとともに、理解も進むようになるでしょう。
35
-
36
34
### これから作るもの {#what-are-we-building}
37
35
38
36
このチュートリアルでは、インタラクティブな三目並べゲーム (tic-tac-toe) の作り方をお見せします。
@@ -190,6 +188,8 @@ Square(マス目)コンポーネントは 1 つの `<button>` をレンダ
190
188
191
189
では手始めに、Board コンポーネントから Square コンポーネントにデータを渡してみましょう。
192
190
191
+ チュートリアルを進めるにあたって、コードをコピー・ペーストしないで、手でタイプすることをお勧めします。そうすれば手が動きを覚えるとともに、理解も進むようになるでしょう。
192
+
193
193
Board の ` renderSquare ` メソッド内で、props として ` value ` という名前の値を Square に渡すようにコードを変更します:
194
194
195
195
``` js{3}
@@ -260,7 +260,7 @@ class Square extends React.Component {
260
260
>}
261
261
>```
262
262
>
263
- > `onClick={() => alert('click')}` と記載したときに `onClick` プロパティに渡しているのは*関数*であることに注意してください。この関数はクリックされるまで実行されません 。`() =>` を書くのを忘れて `onClick={alert('click')}` と書くのはよくある間違いであり、こうするとコンポーネントが再レンダーされるたびにアラートが表示されてしまいます。
263
+ > `onClick={() => alert('click')}` と記載したときに `onClick` プロパティに渡しているのは*関数*であることに注意してください。React はクリックされるまでこの関数を実行しません 。`() =>` を書くのを忘れて `onClick={alert('click')}` と書くのはよくある間違いであり、こうするとコンポーネントが再レンダーされるたびにアラートが表示されてしまいます。
264
264
265
265
次のステップとして、Square コンポーネントに自分がクリックされたことを「覚えさせ」て、"X" マークでマスを埋めるようにさせます。コンポーネントが何かを「覚える」ためには、**state** というものを使います。
266
266
@@ -294,7 +294,7 @@ class Square extends React.Component {
294
294
次に Square の ` render ` メソッドを書き換えて、クリックされた時に state の現在値を表示するようにします。
295
295
296
296
* ` <button> ` タグ内の ` this.props.value ` を ` this.state.value ` に置き換える。
297
- * ` () => alert() ` というイベントハンドラを ` () => this.setState({value: 'X'}) ` に書き換える。
297
+ * ` onClick={...} ` というイベントハンドラを ` onClick={ () => this.setState({value: 'X'})} ` に書き換える。
298
298
* 読みやすくするため、` className ` と ` onClick ` の両プロパティをそれぞれ独立した行に配置する。
299
299
300
300
これらの書き換えの後、Square の ` render ` メソッドから返される ` <button> ` タグは以下のようになります。
@@ -356,7 +356,9 @@ Board が各 Square に、現時点の state がどうなっているか問い
356
356
357
357
** 複数の子要素からデータを集めたい、または 2 つの子コンポーネントに互いにやりとりさせたいと思った場合は、代わりに親コンポーネント内で共有の state を宣言する必要があります。親コンポーネントは props を使うことで子に情報を返すことができます。こうすることで、子コンポーネントが兄弟同士、あるいは親との間で常に同期されるようになります。**
358
358
359
- このように state を親コンポーネントにリフトアップ (lift up) することは React コンポーネントのリファクタリングでよくあることですので、この機会に挑戦してみましょう。Board にコンストラクタを追加し、初期 state をセットして 9 個の null 値を持つ配列が含まれるようにします。この 9 個の null が 9 個のマス目に対応します。
359
+ このように state を親コンポーネントにリフトアップ (lift up) することは React コンポーネントのリファクタリングでよくあることですので、この機会に挑戦してみましょう。
360
+
361
+ Board にコンストラクタを追加し、初期 state に 9 個の null が 9 個のマス目に対応する 9 個の null 値をセットします。
360
362
361
363
``` javascript{2-7}
362
364
class Board extends React.Component {
@@ -370,35 +372,9 @@ class Board extends React.Component {
370
372
renderSquare(i) {
371
373
return <Square value={i} />;
372
374
}
373
-
374
- render() {
375
- const status = 'Next player: X';
376
-
377
- return (
378
- <div>
379
- <div className="status">{status}</div>
380
- <div className="board-row">
381
- {this.renderSquare(0)}
382
- {this.renderSquare(1)}
383
- {this.renderSquare(2)}
384
- </div>
385
- <div className="board-row">
386
- {this.renderSquare(3)}
387
- {this.renderSquare(4)}
388
- {this.renderSquare(5)}
389
- </div>
390
- <div className="board-row">
391
- {this.renderSquare(6)}
392
- {this.renderSquare(7)}
393
- {this.renderSquare(8)}
394
- </div>
395
- </div>
396
- );
397
- }
398
- }
399
375
```
400
376
401
- 後で盤面が埋まっていくと、このような見た目になるでしょう :
377
+ 後で盤面が埋まっていくと、` this.state.squares ` 配列はこのような見た目になるでしょう :
402
378
403
379
``` javascript
404
380
[
@@ -432,7 +408,7 @@ Board の `renderSquare` メソッドは現在以下のようになっていま
432
408
433
409
次に、マス目がクリックされた時の挙動を変更しましょう。現在、どのマス目に何が入っているのかを管理しているのは Board です。Square が Board の state を更新できるようにする必要があります。state はそれを定義しているコンポーネント内でプライベートなものですので、Square から Board の state を直接書き換えることはできません。
434
410
435
- Board の state のプライベート性を保護するため、Board から Square に関数を渡すことにします。この関数はマス目がクリックされた時に呼び出されます 。` renderSquare ` メソッドを以下のように書き換えましょう:
411
+ 代わりに、 Board から Square に関数を渡すことにして、マス目がクリックされた時に Square にその関数を呼んでもらうようにしましょう 。` renderSquare ` メソッドを以下のように書き換えましょう:
436
412
437
413
``` javascript{5}
438
414
renderSquare(i) {
@@ -477,12 +453,12 @@ Square がクリックされると、Board から渡された `onClick` 関数
477
453
1 . 組み込みの DOM コンポーネントである ` <button> ` に ` onClick ` プロパティが設定されているため React がクリックに対するイベントリスナを設定します。
478
454
2 . ボタンがクリックされると、React は Square の ` render() ` メソッド内に定義されている ` onClick ` のイベントハンドラをコールします。
479
455
3 . このイベントハンドラが ` this.props.onClick() ` をコールします。Square の ` onClick ` プロパティは Board から渡されているものです。
480
- 4 . Board は Square に ` onClick={() => this.handleClick(i)} ` を渡していたので、Squre はクリックされたときに ` this.handleClick(i) ` を呼び出します。
481
- 5 . まだ ` handleClick() ` は定義していないので、コードがクラッシュします。
456
+ 4 . Board は Square に ` onClick={() => this.handleClick(i)} ` を渡していたので、Square はクリックされたときに ` this.handleClick(i) ` を呼び出します。
457
+ 5 . まだ ` handleClick() ` は定義していないので、コードがクラッシュします。Square をクリックすると、"this.handleClick is not a function" といった赤いエラー画面が表示されるはずです。
482
458
483
459
> 補足
484
460
>
485
- > DOM 要素である ` <button> ` は組み込みコンポーネントなので、` onClick ` 属性は React にとって特別な意味を持っています。Square のようなカスタムコンポーネントでは、名前の付け方はあなたの自由です。Square の ` onClick ` プロパティや Board の ` handleClick ` メソッドについては別の名前を付けたとしても構いません。しかし React では、イベントを表す props には ` on[Event] ` という名前、イベントを処理するメソッドには ` handle[Event] ` という名前を付けるのが慣習となっています。
461
+ > DOM 要素である ` <button> ` は組み込みコンポーネントなので、` onClick ` 属性は React にとって特別な意味を持っています。Square のようなカスタムコンポーネントでは、名前の付け方はあなたの自由です。Square の ` onClick ` プロパティや Board の ` handleClick ` メソッドについては別の名前を付けたとしても同じように動作します。 React では、イベントを表す props には ` on[Event] ` という名前、イベントを処理するメソッドには ` handle[Event] ` という名前を付けるのが慣習となっています。
486
462
487
463
まだ ` handleClick ` を定義していないので、マス目をクリックしようとするとエラーが出るはずです。この ` handleClick ` を Board クラスに加えましょう。
488
464
@@ -611,7 +587,7 @@ function Square(props) {
611
587
612
588
> 補足
613
589
>
614
- > Square を関数コンポーネントに変えた際、` onClick={() => this.props.onClick()} ` をより短い ` onClick={props.onClick} ` に書き換えました(* 両側* でカッコが消えています)。クラスでは正しい ` this ` の値にアクセスするためにアロー関数を使いましたが、関数コンポーネントでは ` this ` について心配する必要はありません。
590
+ > Square を関数コンポーネントに変えた際、` onClick={() => this.props.onClick()} ` をより短い ` onClick={props.onClick} ` に書き換えました(* 両側* でカッコが消えています)。
615
591
616
592
### 手番の処理 {#taking-turns}
617
593
@@ -643,7 +619,9 @@ class Board extends React.Component {
643
619
}
644
620
```
645
621
646
- この変更により、"X" 側と "O" 側が交互に着手できるようになります。Board の ` render ` 内にある "status" テキストも変更して、どちらのプレーヤの手番なのかを表示するようにしましょう。
622
+ この変更により、"X" 側と "O" 側が交互に着手できるようになります。試してみてください!
623
+
624
+ Board の ` render ` 内にある "status" テキストも変更して、どちらのプレーヤの手番なのかを表示するようにしましょう。
647
625
648
626
``` javascript{2}
649
627
render() {
@@ -714,7 +692,7 @@ class Board extends React.Component {
714
692
715
693
### ゲーム勝者の判定 {#declaring-a-winner}
716
694
717
- どちらの手番なのかを表示できたので、次にやることはゲームが決着して次の手番がなくなった時にそれを表示することです。ファイル末尾に以下のヘルパー関数を加えることで、勝者の判定ができるようになります 。
695
+ どちらの手番なのかを表示できたので、次にやることはゲームが決着して次の手番がなくなった時にそれを表示することです。ファイル末尾に以下のヘルパー関数をコピーして貼り付けてください 。
718
696
719
697
``` javascript
720
698
function calculateWinner (squares ) {
@@ -738,6 +716,8 @@ function calculateWinner(squares) {
738
716
}
739
717
```
740
718
719
+ 9 つの square の配列が与えられると、この関数は勝者がいるか適切に確認し、` 'X' ` か ` 'O' ` 、あるいは ` null ` を返します。
720
+
741
721
Board の ` render ` 関数内で ` calculateWinner(squares) ` を呼び出して、いずれかのプレーヤが勝利したかどうか判定します。決着がついた場合は "Winner: X" あるいは "Winner: O" のようなテキストを表示するとよいでしょう。Board の ` render ` 関数の ` status ` 宣言を以下のコードで置き換えましょう。
742
722
743
723
``` javascript{2-8}
0 commit comments