技術ログ

map() の実験全貌 - React.js

2019年9月22日

(ここら辺の本を一通り読んで凄いと思ったので紹介、記事は分かりにくいかもしれないので、是非本かって読んでください、基本を徹底するのが良いエンジニアの共通点)

 

さて

本日は、私も現在勉強中のReact.jsでございます。

本で学んで自分で書いてみて、実行して、頭にいれる。

みたいなやり方を実践しました!

では行ってみよう〜

リストとキー

まず、JavaScriptでリストをどのように変換するかを見てみましょう。以下のコードでは、map()関数を使用して数値の配列をとり、それらの値を2倍にします。 map()によって返された新しい配列を変数doubledに代入してログに記録します

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

このコードは [2,4,6,8,10] をコンソールに記録します。

複数のコンポーネントのレンダリング

要素のコレクションを作成し、中括弧{}を使用してJSXに含めることができます。以下では、Javascriptのmap()関数を使用してnumbers配列をループします。各アイテムに要素を返します。最後に、結果の要素の配列をlistItemsに割り当てます。

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li>{number}</li>
);

listItems配列全体を<ul>要素の中に含め、それをDOMにレンダリングします。

ReactDOM.render(
  <ul>{listItems}</ul>,
  document.getElementById('root')
);

CodePenで試してみてください。

このコードは1から5までの数字の箇条書きリストを表示します。

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

通常は、コンポーネントをリスト内にレンダリングします。数値の配列を受け取り、順序付けられていない要素のリストを出力するコンポーネントに、リファクタリングすることができます。

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li>{number}</li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

このコードを実行すると、リスト項目に キー を提供する必要があるという警告が表示されます。 "キー"は、要素のリストを作成するときに含める必要がある特別な文字列属性です。次のセクションで重要な理由について説明します。 numbers.map() 内のリスト項目にキーを割り当て、欠落しているキーの問題を修正しましょう。

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>

    //ここ
    <li key={number.toString()}>
      {number}
    </li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

CodePenで試してみてください。

Keys

キーは、どのアイテムが変更されたのか、追加されたのか、削除されたのかを識別します。要素に安定した ユニークを与えるために、配列内の要素にキーを与える必要があります。

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  //ここ
  <li key={number.toString()}>
    {number}
  </li>
);

キーを選択する最も良い方法は、兄弟間でリスト項目を一意に識別する文字列を使用することです。多くの場合、データのIDをキーとして使用します。

const todoItems = todos.map((todo) =>
  //ここ
  <li key={todo.id}>
    {todo.text}
  </li>
);

レンダリングされたアイテムのIDが安定していない場合は、アイテムインデックスを最後の手段としてキーとして使用できます。

const todoItems = todos.map((todo, index) =>
  // アイテムに安定したIDがない場合にのみ行う
  <li key={index}>
    {todo.text}
  </li>
);

キーによるコンポーネントの抽出

キーは、周囲の配列のコンテキストでのみ意味があります。たとえば、 ListItem コンポーネントを抽出する場合は、 ListItem 自体のルート <li> 要素ではなく、配列の <ListItem /> 要素にキーを保持する必要があります。

例:不正なキーの使用

function ListItem(props) {
  const value = props.value;
  return (
    // ここでキーを指定する必要はありません。
    <li key={value.toString()}>
      {value}
    </li>
  );
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // キーはここで指定されるべきです
    <ListItem value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

例:正しいキーの使用法

function ListItem(props) {
  // ここでキーを指定する必要はありません。
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // キーは配列内で指定する必要があります。
    <ListItem key={number.toString()}
              value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

CodePenで試してみてください。

経験則として、map()コールの中の要素にはキーが必要です。

キーは唯一の兄弟でなければならない

配列内で使用されるキーは、兄弟間で一意でなければなりません。しかし、それらは世界的にユニークである必要はありません。 2つの異なる配列を生成する場合、同じキーを使用できます。

function Blog(props) {
  const sidebar = (
    <ul>
      {props.posts.map((post) =>
        <li key={post.id}>
          {post.title}
        </li>
      )}
    </ul>
  );
  const content = props.posts.map((post) =>
    <div key={post.id}>
      <h3>{post.title}</h3>
      <p>{post.content}</p>
    </div>
  );
  return (
    <div>
      {sidebar}
      <hr />
      {content}
    </div>
  );
}

const posts = [
  {id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
  {id: 2, title: 'Installation', content: 'You can install React from npm.'}
];
ReactDOM.render(
  <Blog posts={posts} />,
  document.getElementById('root')
);

CodePenで試してみてください。

キーはReactへのヒントとして機能しますが、コンポーネントに渡されることはありません。コンポーネントに同じ値が必要な場合は、別の名前のプロップとして明示的に渡します。

const content = posts.map((post) =>
  <Post
    key={post.id}
    id={post.id}
    title={post.title} />
);

上記の例では、Postコンポーネントはprops.idを読み取ることができますが、props.keyは読み取ることができません。

JSXにmap()を埋め込む

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

JSX では、任意の式を中括弧{} で埋め込むことができるので、map()の結果をインライン展開できます。

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

CodePenで試してみてください。

場合によってはこれによりコードがより明確になることもありますが、このスタイルも悪用される可能性があります。 JavaScript のように、可読性のために変数を抽出する価値があるかどうかを判断するのは、あなた次第です。

以上になります!!!ありがとうございました

 

Pocket
LinkedIn にシェア

ご報告

off.tokyoは法人化しました、Web/Mobile コンサルティングのご相談なら、bid companyへお問い合わせください :)

ご提供 sponsor
 

Meee!(ミー)は、ビジネスからプライベート利用まで、個人のスキルを気軽に売り買いできるスキルマーケットです。カテゴリや居住地から、検索することが可能です。

 

ランゲージエクスチェンジは、ネイティブスピーカーと気軽にマッチングできる言語交換プラットフォームです。あなたの地元に住む外国人を探したり、留学や海外移住の前に、現地のネイティブスピーカーと繋がることもできます!

宣伝
 

りょすけトークchは、仕事や私生活をより豊にするYouTubeチャンネルです。文献(本、映画、論文)から役に立つ情報をまとめ、生涯にわたり役に立つ哲学をお届けしています。是非、チャンネル登録してみてね

  • この記事を書いた人

ryosuke-hujisawa

-技術ログ

Copyright© off , 2020 All Rights Reserved Powered by AFFINGER5.