Reactガイドを読んでいくその10

これは

Reactのガイドを読んでいく記事です。

ガイドのリンク

ja.reactjs.org

リストと key

JavaScriptではmap()を使ってリスト変換をします。

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);   // [2,4,6,8,10]

Reactもほぼ同様の機能を持っています。
Reactは中括弧で囲むことで実現することが可能です。

const numbers = [1, 2, 3, 4, 5];
// JavaScriptとは書き方が異なる点注意
// ここだけ考えるとJavaScriptの方が簡単に見える。
const listItems = numbers.map((number) =>
  <li>{number}</li>
);

ReactDOM.render(
// DOMへ上で行ったlistitemを出力するようにしている
  <ul>{listItems}</ul>,
  document.getElementById('root')
);
/*
・1
・2
・3
・4
・5
*/

基本的なリストコンポーネント

コンポーネント内部でレンダリングしたい場合リスト項目にはkeyが必要となります。
実行はするもののワーニングを出すので、対応しておくべき項目になります。

"Warning: Each child in a list should have a unique 'key' prop.%s%s See https://fb.me/react-warning-keys for more information.%s" "

Check the top-level render call using <ul>." "" "
    in li"

チュートリアルをやっているときにやった内容ですね。

Key

KeyはReactがどの要素が変更・追加・削除されたのかを識別するのに役立ち、 それぞれ一意にIDが振られることでReactが少ない処理で動くことができるようになります。
IDを触れない場合はインデックスという形で処理をすることが可能ですが、処理速度は遅くなるので忌避される。

key のあるコンポーネントの抽出

map()の呼び出しのなかに登場する要素にkeyをつけるという考え方が基本となります。
なので、以下のような場合は不適切。

function ListItem(props) {
  const value = props.value;
  return (
    // Wrong! There is no need to specify the key here:
    <li key={value.toString()}>
      {value}
    </li>
  );
}

正解はこちらになります。

function ListItem(props) {
  // Correct! There is no need to specify the key here:
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // Correct! Key should be specified inside the array.
    <ListItem key={number.toString()}
              value={number} />

  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

なのでkey が意味を持つのは、それをとり囲んでいる配列の側の文脈となります。

key は兄弟要素の中で一意であればよい

keyそのものは全体で一意である必要はないが、配列内では一意である必要があります。
配列一つ一つが独立したDBと考えれば、当然と言えば当然と言えます。
keyはReact側に必要な情報であって、コンポーネントとしては不要で、渡されることのない情報になります。

map() を JSX に埋め込む

JSXでは任意の式の埋め込みが可能なので、map()も埋め込みが可能。
スッキリして見えるのでよく使われる方法だが、コード規約に則り多用は考えて使うことが求められる。
Before

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <ListItem key={number.toString()}
              value={number} />

  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

After

function NumberList(props) {
  const numbers = props.numbers;
  return (
    <ul>
      {numbers.map((number) =>
        <ListItem key={number.toString()}
                  value={number} />

      )}
    </ul>
  );
}

今日はここまで。