@samitouri / QOS-React / commits / 9c7f895783

Updte tutorial to ja-JP (#6967)

ogom committed Jun 9, 2016 at 11:20 UTC 9c7f8957835b1dfd34cb12aa7ed8ffafae7d182a
1 file changed +122 -42
docs/docs/tutorial.ja-JP.md
+122 -42
@@ -40,7 +40,7 @@ next: thinking-in-react-ja-JP.html
40 <html>
41 <head>
42 <meta charset="UTF-8" />
43 - <title>Hello React</title>
43 + <title>React Tutorial</title>
44 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react.js"></script>
45 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/{{site.react_version}}/react-dom.js"></script>
46 <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
@@ -289,8 +289,8 @@ var Comment = React.createClass({
289 ```javascript
290 // tutorial8.js
291 var data = [
292 - {author: "Pete Hunt", text: "This is one comment"},
293 - {author: "Jordan Walke", text: "This is *another* comment"}
292 + {id: 1, author: "Pete Hunt", text: "This is one comment"},
293 + {id: 2, author: "Jordan Walke", text: "This is *another* comment"}
294 ];
295 ```
296
@@ -347,7 +347,7 @@ var CommentList = React.createClass({
347 ```javascript{3}
348 // tutorial11.js
349 ReactDOM.render(
350 - <CommentBox url="api/comments" />,
350 + <CommentBox url="/api/comments" />,
351 document.getElementById('content')
352 );
353 ```
@@ -389,8 +389,8 @@ var CommentBox = React.createClass({
389
390 ```json
391 [
392 - {"author": "Pete Hunt", "text": "This is one comment"},
393 - {"author": "Jordan Walke", "text": "This is *another* comment"}
392 + {"id": "1", "author": "Pete Hunt", "text": "This is one comment"},
393 + {"id": "2", "author": "Jordan Walke", "text": "This is *another* comment"}
394 ]
395 ```
396
@@ -466,7 +466,7 @@ var CommentBox = React.createClass({
466 });
467
468 ReactDOM.render(
469 - <CommentBox url="comments.json" pollInterval={2000} />,
469 + <CommentBox url="/api/comments" pollInterval={2000} />,
470 document.getElementById('content')
471 );
472
@@ -476,7 +476,7 @@ ReactDOM.render(
476
477 ### 新しいコメントの追加
478
479 -いよいよフォームを作る段階に来ました。ここで `CommentForm` コンポーネントは、ユーザに自分の名前とコメントの内容を入力させ、コメントを保存させるためにサーバへリクエストを送る役割を果たすことになります。
479 +いよいよフォームを作る段階に来ました。ここで `CommentForm` コンポーネントは、ユーザに自分の名前とコメントの内容を入力させ、コメントを保存するためにサーバにリクエストを送信する必要があります。
480
481 ```javascript{5-9}
482 // tutorial15.js
@@ -493,28 +493,93 @@ var CommentForm = React.createClass({
493 });
494 ```
495
496 -それでは、フォームを使ってデータをやり取りできるようにしましょう。ユーザがフォームから送信したら、フォームをクリアしてサーバにリクエストを送り、コメントリストをリフレッシュすることになります。まず手始めに、フォームからの送信イベントを受け取ってフォームをクリアできるようにしましょう。
496 +#### 制御コンポーネント
497
498 -```javascript{3-13,16-19}
498 +このチュートリアルの DOM は、`input` 要素がレンダリングされ、ブラウザが状態(そのレンダリングされた値)を管理します。その結果、実際のDOMの状態がコンポーネントとは異なります。ビューの状態がコンポーネントとは異なり、これは理想的ではありません。React では、コンポーネントは初期化の時点だけでなく、常にビューの状態を表している必要があります。
499 +
500 +したがって、ユーザの入力を保存するために `this.state` を使用することになります。2つのプロパティの`author`と`text`に最初の`state`を定義して、空の文字列を設定します。`<input>`の要素では、`onChange`にハンドラをアタッチすると`value` に `state` が反映される。これらの `<input>` の要素は、`value` が設定された制御コンポーネントと呼ばれています。制御コンポーネントの詳細についてはこちらの[Forms article](/react/docs/forms.html#controlled-components)をご覧ください。
501 +
502 +```javascript{3-11,15-26}
503 // tutorial16.js
504 var CommentForm = React.createClass({
505 + getInitialState: function() {
506 + return {author: '', text: ''};
507 + },
508 + handleAuthorChange: function(e) {
509 + this.setState({author: e.target.value});
510 + },
511 + handleTextChange: function(e) {
512 + this.setState({text: e.target.value});
513 + },
514 + render: function() {
515 + return (
516 + <form className="commentForm">
517 + <input
518 + type="text"
519 + placeholder="Your name"
520 + value={this.state.author}
521 + onChange={this.handleAuthorChange}
522 + />
523 + <input
524 + type="text"
525 + placeholder="Say something..."
526 + value={this.state.text}
527 + onChange={this.handleTextChange}
528 + />
529 + <input type="submit" value="Post" />
530 + </form>
531 + );
532 + }
533 +});
534 +```
535 +
536 +#### イベント
537 +
538 +React イベントハンドラのアタッチはコンポーネントにキャメルケースの命名規則を使用します。2つの`<input>`要素に`onChange`のハンドラをアタッチします。今、ユーザーの入力は`<input>`フィールド、アタッチされた`onChange`がコールバックされてコンポーネントの` state`が変更されます。その後、`input`要素のレンダリングされた値は、現在のコンポーネント` state`を反映するように更新されます。
539 +
540 +(賢明な読者は、説明したようにこれらのイベントハンドラが動作することを驚かれるかもしれない、明示的な結合を不要にそのコンポーネントインスタンスへの各メソッドは、メソッドの参照が明示的に`this`. `React.createClass(...)` [automatically binds](/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation)にバインドされていないことを自動的に結合する与えられました。)
541 +
542 +#### フォーム送信
543 +
544 +フォームを対話型にしましょう。ユーザーがフォームを送信すると、それをクリアする必要があります。サーバに要求を送信すると、コメントのリストを更新します。開始するとフォームの送信イベントでクリアするか試しましょう。
545 +
546 +```javascript{12-21,24}
547 +// tutorial17.js
548 +var CommentForm = React.createClass({
549 + getInitialState: function() {
550 + return {author: '', text: ''};
551 + },
552 + handleAuthorChange: function(e) {
553 + this.setState({author: e.target.value});
554 + },
555 + handleTextChange: function(e) {
556 + this.setState({text: e.target.value});
557 + },
558 handleSubmit: function(e) {
559 e.preventDefault();
503 - var author = ReactDOM.findDOMNode(this.refs.author).value.trim();
504 - var text = ReactDOM.findDOMNode(this.refs.text).value.trim();
560 + var author = this.state.author.trim();
561 + var text = this.state.text.trim();
562 if (!text || !author) {
563 return;
564 }
508 - // TODO: サーバにリクエストを送信
509 - ReactDOM.findDOMNode(this.refs.author).value = '';
510 - ReactDOM.findDOMNode(this.refs.text).value = '';
511 - return;
565 + // TODO: サーバーに要求を送信
566 + this.setState({author: '', text: ''});
567 },
568 render: function() {
569 return (
570 <form className="commentForm" onSubmit={this.handleSubmit}>
516 - <input type="text" placeholder="Your name" ref="author" />
517 - <input type="text" placeholder="Say something..." ref="text" />
571 + <input
572 + type="text"
573 + placeholder="Your name"
574 + value={this.state.author}
575 + onChange={this.handleAuthorChange}
576 + />
577 + <input
578 + type="text"
579 + placeholder="Say something..."
580 + value={this.state.text}
581 + onChange={this.handleTextChange}
582 + />
583 <input type="submit" value="Post" />
584 </form>
585 );
@@ -522,24 +587,18 @@ var CommentForm = React.createClass({
587 });
588 ```
589
525 -##### イベント
526 -
527 -React がコンポーネントにイベントハンドラを登録する際は camelCase の命名規則に従います。上のコードではフォームに `onSubmit` ハンドラを登録し、フォームから妥当な入力が送信されたらフォームをクリアするようになっています。
528 -
529 -また `preventDefault()` を呼び出しているので、フォームからの送信に対してブラウザのデフォルト処理が反応することはありません。
590 +フォームが有効な入力でサブミットされたときにフォームフィールドをクリアし、フォームに`onSubmit`ハンドラをアタッチします。
591
531 -##### Refs
592 +`preventDefault()` はフォームを送信するイベントにブラウザのデフォルトのアクションを防ぐためにコールします。
593
533 -先程のコードでは `ref` 属性値を使って子のコンポーネントに名前を付けており、`this.ref` でそのコンポーネントを参照しています。`ReactDOM.findDOMNode(component)` にコンポーネントを指定して呼び出すことで、ブラウザの持つ実際の DOM 要素を取得することが出来ます。
534 -
535 -##### Props としてのコールバック
594 +#### Props としてのコールバック
595
596 ユーザがコメントを送信したら、コメントリストをリフレッシュして新しいリストを読み込むことになります。コメントリストを表す state を保持しているのは `CommentBox` なので、必要なロジックは `CommentBox` の中に書くのが筋でしょう。
597
598 ここでは子のコンポーネントから親に向かって、いつもとは逆方向にデータを返す必要があります。まず、親のコンポーネントに新しいコールバック関数(`handleCommentSubmit`)を定義します。続いて `render` メソッド内にある子のコンポーネントにコールバックを渡すことで、`onCommentSubmit` イベントとコールバックを結び付けています。こうすることで、イベントが発生するたびにコールバックが呼び出されます。
599
600 ```javascript{16-18,31}
542 -// tutorial17.js
601 +// tutorial18.js
602 var CommentBox = React.createClass({
603 loadCommentsFromServer: function() {
604 $.ajax({
@@ -555,7 +614,7 @@ var CommentBox = React.createClass({
614 });
615 },
616 handleCommentSubmit: function(comment) {
558 - // TODO: サーバに送信、リストをリフレッシュ
617 + // TODO: submit to the server and refresh the list
618 },
619 getInitialState: function() {
620 return {data: []};
@@ -576,28 +635,45 @@ var CommentBox = React.createClass({
635 });
636 ```
637
579 -それでは、ユーザがフォームから送信したら `CommentForm` がコールバックを呼び出せるようにしましょう。
638 +今、`CommentBox`は`onCommentSubmit`をpropして`CommentForm`にコールバックを利用した、ユーザーがフォームを送信したときに`CommentForm`はコールバックを呼び出すことができます。
639
581 -```javascript{10}
582 -// tutorial18.js
640 +```javascript{19}
641 +// tutorial19.js
642 var CommentForm = React.createClass({
643 + getInitialState: function() {
644 + return {author: '', text: ''};
645 + },
646 + handleAuthorChange: function(e) {
647 + this.setState({author: e.target.value});
648 + },
649 + handleTextChange: function(e) {
650 + this.setState({text: e.target.value});
651 + },
652 handleSubmit: function(e) {
653 e.preventDefault();
586 - var author = ReactDOM.findDOMNode(this.refs.author).value.trim();
587 - var text = ReactDOM.findDOMNode(this.refs.text).value.trim();
654 + var author = this.state.author.trim();
655 + var text = this.state.text.trim();
656 if (!text || !author) {
657 return;
658 }
659 this.props.onCommentSubmit({author: author, text: text});
592 - ReactDOM.findDOMNode(this.refs.author).value = '';
593 - ReactDOM.findDOMNode(this.refs.text).value = '';
594 - return;
660 + this.setState({author: '', text: ''});
661 },
662 render: function() {
663 return (
664 <form className="commentForm" onSubmit={this.handleSubmit}>
599 - <input type="text" placeholder="Your name" ref="author" />
600 - <input type="text" placeholder="Say something..." ref="text" />
665 + <input
666 + type="text"
667 + placeholder="Your name"
668 + value={this.state.author}
669 + onChange={this.handleAuthorChange}
670 + />
671 + <input
672 + type="text"
673 + placeholder="Say something..."
674 + value={this.state.text}
675 + onChange={this.handleTextChange}
676 + />
677 <input type="submit" value="Post" />
678 </form>
679 );
@@ -608,7 +684,7 @@ var CommentForm = React.createClass({
684 こうしてコールバックが出来たので、あとはサーバにコメントを送信してリストをリフレッシュすれば完璧です。
685
686 ```javascript{17-28}
611 -// tutorial19.js
687 +// tutorial20.js
688 var CommentBox = React.createClass({
689 loadCommentsFromServer: function() {
690 $.ajax({
@@ -660,8 +736,8 @@ var CommentBox = React.createClass({
736
737 アプリケーションに必要な機能は一通り実装できました。しかし、フォームからコメントを送信しても、サーバからのレスポンスが来るまで自分のコメントはリストに載らないため、アプリの動作は遅く感じます。ここでは、送信したコメントをリストに先読みさせて、アプリの体感速度をアップさせましょう。
738
663 -```javascript{17-19,29}
664 -// tutorial20.js
739 +```javascript{17-23,33}
740 +// tutorial21.js
741 var CommentBox = React.createClass({
742 loadCommentsFromServer: function() {
743 $.ajax({
@@ -678,6 +754,10 @@ var CommentBox = React.createClass({
754 },
755 handleCommentSubmit: function(comment) {
756 var comments = this.state.data;
757 + // Optimistically set an id on the new comment. It will be replaced by an
758 + // id generated by the server. In a production application you would likely
759 + // not use Date.now() for this and would have a more robust system in place.
760 + comment.id = Date.now();
761 var newComments = comments.concat([comment]);
762 this.setState({data: newComments});
763 $.ajax({