Reactを初めて触ってみました(tutorialその⑧)
このページはReact公式ページのtutorialを体験したメモと初心者なりの解釈を記述したページになります。
前回まではゲームコンポーネントへ状態を保存する部分を移していき履歴の保存する部分の準備をした感じです。
※WEB翻訳をそのまま載せているところもありますが自分で理解できるように記事にしています。
チュートリアルの理解なのにこれの記事が長くなってしまって申し訳なくなってきました。。。
でもやりきりらないとはじまりませんのでやっていきましょう!!
ムーブメントの表示
前回React要素はファーストクラスのJSオブジェクトであることを知り、保存したり、渡したりしました。
Reactで複数の項目をレンダリングするには、React要素の配列を渡します。
その配列を構築する最も一般的な方法は、データの配列をマップすることです。
Gameのrenderメソッドでそれをやってみましょう。
render() {
const history = this.state.history;
const current = history[history.length - 1];
const winner = calculateWinner(current.squares);
const moves = history.map((step, move) => {
const desc = move ?
'Go to move #' + move :
'Go to game start';
return (
<li>
<button onClick={() => this.jumpTo(move)}>{desc}</button>
</li>
);
});
let status;
if (winner) {
status = 'Winner: ' + winner;
} else {
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}
return (
<div className="game">
<div className="game-board">
<Board
squares={current.squares}
onClick={(i) => this.handleClick(i)}
/>
</div>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
);
}
ヒストリの各ステップについて、すぐに実装するクリックハンドラを持つボタン<button>を含むリストアイテム<li>を作成します。
このコードを実装すると、ゲーム内で行われた移動の一覧と、警告が表示されます。
Warning: Each child in an array or iterator should have a unique “key” prop. Check the render method of “Game”.
ではなぜ警告がでているのかの説明です。
Key
アイテムのリストをレンダリングすると、Reactは常に各アイテムの情報をリストに保存します。
状態を持つコンポーネントをレンダリングする場合は、当然その状態を保存している必要があります。
コンポーネントの実装方法に関係なく、Reactは、バッキングネイティブビューへの参照を保存します。
そのリストを更新するとき、Reactは何が変更されたかを判断する必要があります。
リスト内の項目を追加、削除、再配置、または更新できました。
下の表示変化を想像してください。
<li>Alexa: 7 tasks left</li>
<li>Ben: 5 tasks left</li>
から
<li>Ben: 9 tasks left</li>
<li>Claudia: 8 tasks left</li>
<li>Alexa: 5 tasks left</li>
人間の目には、AlexaとBenが場所を入れ替え、Claudiaが追加されたように見えますが、Reactは単なるコンピュータプログラムであり、あなたが意図したことは分かりません。
その結果、Reactは、リスト内の各要素にキープロパティを指定し、各コンポーネントを兄弟(兄弟要素)と区別するための文字列を指定するよう求めます。
この場合、アレクサ、ベン、クラウディアは人間的には感覚的な鍵になるかもしれません。
※でもReactは区別するための明示的なKeyが必要なんですね。ゴリゴリjavascriptで要素の置換か何かをする時も必要なのでイメージはできます。
アイテムがデータベース内のオブジェクトに対応する場合、通常はデータベースIDが適切です。
※まとめると私の解釈的にはここではそれぞれの名前が違うので人間の視覚的には名前をキーとして判断できますがReactはそれでは判断できないのでkeyプロパティーを必要とし>ます。それはデータベースの一意なキーが適切でしょう。と言うようなことをおっしゃ>っているんだと思います。
<li key={user.id}>{user.name}: {user.taskCount} tasks left</li>
keyはReactによって予約されている特別なプロパティです。要素が作成されると、Reactはキープロパティをプルオフし、キーを返された要素に直接格納します。それは小道具(props)の一部であるように見えるかもしれませんが、this.props.keyで参照することはできません。 Reactはキーを自動的に使用して、更新する子を決定します。
コンポーネントが独自のキーについて問い合わせる方法はありません。
リストが再レンダリングされると、Reactは新しいバージョンの各要素を受け取り、前のリストで一致するキーを持つ要素を探します。
※私の解釈的なのいっときます。
keyプロパティはReactの予約プロパティで要素が作成されると要素にあるKeyを取得して格納し状態変化の差分時にはそのKeyを元に更新をしてくれるということでしょうか。
キーがセットに追加されると、コンポーネントが作成されます。キーが削除されると、コンポーネントが破棄されます。
キーはReactに各コンポーネントのアイデンティティを伝えるので、rerenders間で状態を維持することができます。
コンポーネントのキーを変更すると、コンポーネントは完全に破棄され、新しい状態で再作成されます。
※Key単位でのパーツとして認識して、Keyがなくなればそのパーツも削除され新た物があれば新規に作成される。Keyの変更も同様でKeyが無くなり対応するパーツが削除され更新された新たなKeyのパーツが出来上がるというわけですね。
それはrender間で維持されている。
動的リストを作成するたびに、適切なキーを割り当てることを強くお勧めします。
適切なキーを手元に置いていない場合は、データの再構成を検討してください。
キーを指定しない場合、Reactはあなたに警告し、配列インデックスをキーとして使用することに戻ります。
リストの要素を並べ替えたり、項目の追加/削除を行う場合には正しい選択ではありませんリスト。
明示的にkey = {i}を渡すと警告が消えますが、同じ問題がありますので、ほとんどの場合は推奨されません。
コンポーネントキーは、グローバルに一意である必要はなく、直接の兄弟に対して一意である必要があります。
※兄弟要素がある場合にKeyが無ければreactは警告を出し配列のインデックスをKeyとしておきますがあまりいいやり方ではないと。。警告はKeyを設置すれば消えます。
key = {i}とすれば消えますが問題点は同じで配列のインデクスを指定されたのと代わりません。ですのでKeyをちゃんと指定しましょう。それは兄弟要素で一意であればいいと言うことです。先ほど一意なとしましたが、兄弟要素で一意ということみたいですね。
これで警告がでている意味がわかりました。
なかなかtutorialの解説も長くなってきましたね。
見てる人が同じ初心者で一緒に理解できればなんて考えながら書いていきのは難しいですね。。
でも自分への理解は高まるので自己満足ですが楽しいです。
まだ続きがありますので次回に続きます!!
←Reactを初めて触ってみました(tutorialその⑦)
コメント
コメントを投稿