Reactでの配列ループ利用方法をおさらいする

Reactで配列ループの利用方法をおさらいするため、Reactのドキュメント <a href="https://reactjs.org/docs/lists-and-keys.html#keys" target="_blank" rel="nofollow noopener">Lists and Keys - React</a> を読みつつ調べたことをまとめようと思います。

## サンプルコード

6色の色を配列で定義し、それをReactで ```table``` としてレンダリングする簡単なサンプルを作りました。

<p data-height="265" data-theme-id="0" data-slug-hash="GdVjGr" data-default-tab="js" data-user="gotchane" data-embed-version="2" data-pen-title="ColorTable" class="codepen">See the Pen <a href="https://codepen.io/gotchane/pen/GdVjGr/">ColorTable</a> by Masayuki Goto (<a href="https://codepen.io/gotchane">@gotchane</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

コードも貼っておきます。

``` react
const colors = ['Red','Orange','Yellow','Green','Blue','Violet'];
  
class ColorTable extends React.Component {  
  renderTable() {
    const rows = colors.map((color,index) =>
      <tr key={color}>
        <td>
          {index + 1}
        </td>
        <td>{color}</td>
      </tr>
    );
                            
    return (
      <table border='1' cellSpacing='0'>
         <thead>
            <tr>
               <th>Number</th>
               <th>Name</th>
            </tr>
         </thead>
         <tbody>
           {rows}
         </tbody> 
      </table>
    )
  }
  
  render() {
    return (
      <div>
        {this.renderTable()}
      </div>
    )
  }
};


class App extends React.Component {
  render() {
    return (
      <div>
        <h2>ColorTable</h2>
        <ColorTable />
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
```

## 配列ループ利用時のポイント

### 配列ループにはArray.prototype.map()を使う

Reactのドキュメントにもあるように、配列のループには <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" target="_blank" rel="nofollow noopener">Array.prototype.map()</a>を使います。```Array.prototype.map()``` は、配列要素全てに対し与えられた関数で処理し、新しい配列を戻り値として返す関数です。

```Array.prototype.map()``` を使うことで、値に更新があっても、新しく作った配列を再レンダリングすれば良いような形にしているのかなと思います。

### 配列ループの要素には一意なKeyを指定する

配列ループで要素を作成する際には、 ```props``` に ```key``` を指定します。
これはReactの仮想DOMの差分を反映させる際、最小限のDOM変更にするために利用されます。

``` react
    const rows = colors.map((color,index) =>
      <tr key={color}>
        <td>
          {index + 1}
        </td>
        <td>{color}</td>
      </tr>
    );
```

もし下記のように、Keyとなる値に重複した値を指定したとします。 ```Red``` を重複させてみました。

``` react
const colors = ['Red','Red','Yellow','Green','Blue','Violet'];
```

すると下記のような警告メッセージが出ます。一意になっていないと要素が重複したり省略されたりして、予期せぬ挙動が起こる可能性があるというメッセージですね。

```
Warning: Encountered two children with the same key, `Red`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.
```

Reactが各要素を識別できるよう、一意の ```key``` を指定してあげる必要があります。

### keyはループ対象要素の一番上の階層に設定する

要素に指定する ```key``` の位置ですが、```tr > td``` のようにネストした要素の場合は、一番上の階層に ```key``` を設定する必要があります。（ここでかなりハマりました。。）

もし下記のように、 ```tr``` ではなく一つ下の階層の ```td``` に ```key``` を指定したとします。

``` react
    const rows = colors.map((color,index) =>
      <tr>
        <td key={color}>
          {index + 1}
        </td>
        <td>{color}</td>
      </tr>
    );
```

すると下記のような警告メッセージが出ます。そもそも```key``` をReactが認識出来ていないようなメッセージですね。

```
Warning: Each child in an array or iterator should have a unique 'key' prop.
```

```ul > li``` のように、ループする要素がネストしていない場合は考慮しなくて良いと思いますが、複雑な要素をループさせるときには、ループしている要素の一番上の階層に ```key``` を指定することが必要だと思います。


## 参考サイト

* <a href="https://reactjs.org/docs/lists-and-keys.html#keys" target="_blank" rel="nofollow noopener">Lists and Keys - React</a>
* <a href="https://qiita.com/koba04/items/a4d23245d246c53cd49d" target="_blank" rel="nofollow noopener">React.jsの地味だけど重要なkeyについて</a>