配列の map

Part 0 · React の前に

配列の map

リスト表示のすべてがここから始まる

React の画面は、そのほとんどが「配列を並べたもの」でできています。 商品の一覧、コメント、検索結果、メニュー。 データの中身が違うだけで、やっていることは全部同じです。

そして React でそれを書くとき、必ず出てくるのが map です。

ここが曖昧なままだと、React のコードが一生読めません。 逆にここさえ押さえれば、リスト表示は全部同じ形に見えてきます。

map は「ひとつずつ作り変える」

map は配列のメソッドで、やることはひとつだけです。

123(n) => n * 2結果246
元の配列はそのまま。map が返すのは、別に作られた新しい配列

map に渡しているのは関数です。前の章でやった 「関数を他の関数に渡す」が、さっそくここで出てきます。

数値をひとつずつ 2 倍にする

元の配列は変わらず、新しい配列が返ってくる

numbers(元の配列)
[1, 2, 3]
doubled(map の結果)
[2, 4, 6]

注目してほしいのは、元の numbers が変わっていないことです。map は元の配列に手を加えません。 別の配列を新しく作って返すだけです。

前の章で「React では値を書き換えず、新しく作る」と書きました。map はまさにその考え方でできています。 React と相性がいいのはそのためです。

map-basic.ts

export const numbers = [1, 2, 3];

// ひとつずつ 2 倍にして、新しい配列を作る
export const doubled = numbers.map((n) => n * 2);

// numbers 自体はいっさい変わっていない

オブジェクトの配列から取り出す

実際のデータは、たいていオブジェクトの配列です。 そこから必要なものだけを取り出したり、別の形に整えたりするのにも map を使います。

名前だけを取り出す / 表示用の文字列を作る

渡す関数を変えれば、作られるものも変わる

names
["さとう", "すずき", "たかはし"]
labels
["さとう(20)", "すずき(25)", "たかはし(30)"]

map が返すものは、渡した関数が何を返すかで決まります。 数値を返せば数値の配列、文字列を返せば文字列の配列になります。

map-object.ts

const members = [
  { id: 1, name: "さとう", age: 20 },
  { id: 2, name: "すずき", age: 25 },
  { id: 3, name: "たかはし", age: 30 },
];

// オブジェクトの配列から、名前だけを取り出す
export const names = members.map((member) => member.name);

// 別の形に作り変えることもできる
export const labels = members.map((member) => `${member.name}(${member.age})`);

React では JSX を返す

ここまでくれば、React のリスト表示はもう読めます。 返すものを画面の部品にするだけです。

{members.map((member) => (
  <li key={member.id}>{member.name}</li>
))}

map が返しているのは「画面の部品が入った配列」です。React はそれを受け取って、順番に並べて表示します。

for 文を書いて 1 行ずつ追加していく、という手順は登場しません。 「この配列を、この形に変えたものを表示したい」と書くだけです。

map-object.ts

const members = [
  { id: 1, name: "さとう", age: 20 },
  { id: 2, name: "すずき", age: 25 },
  { id: 3, name: "たかはし", age: 30 },
];

// オブジェクトの配列から、名前だけを取り出す
export const names = members.map((member) => member.name);

// 別の形に作り変えることもできる
export const labels = members.map((member) => `${member.name}(${member.age})`);

ついでに覚えておくと便利なもの

map と同じ形で使える仲間がいます。 いま完璧に覚える必要はありませんが、名前だけ知っておくと読むときに困りません。

const numbers = [1, 2, 3, 4, 5];

// 条件に合うものだけ残す
numbers.filter((n) => n > 2); // [3, 4, 5]

// 条件に合う最初の 1 つを探す
numbers.find((n) => n > 2); // 3

// ひとつの値にまとめる
numbers.reduce((sum, n) => sum + n, 0); // 15

どれも関数を受け取るという点で共通しています。 やはり「関数を値として渡せる」ことが土台になっています。

map-basic.ts

export const numbers = [1, 2, 3];

// ひとつずつ 2 倍にして、新しい配列を作る
export const doubled = numbers.map((n) => n * 2);

// numbers 自体はいっさい変わっていない

理解できたか確かめる

確認クイズ

const doubled = numbers.map((n) => n * 2); を実行したあと、numbers はどうなっている?

確認クイズ

members.map((member) => member.name) が返すのは?

map-basic.ts

export const numbers = [1, 2, 3];

// ひとつずつ 2 倍にして、新しい配列を作る
export const doubled = numbers.map((n) => n * 2);

// numbers 自体はいっさい変わっていない

この章のまとめ

  • map は、要素をひとつずつ関数に通して新しい配列を返す
  • 元の配列は変わらない
  • 返ってくるものの中身は、渡した関数が何を返すかで決まる
  • React では、関数が画面の部品を返すようにする。 これがリスト表示の正体

map-basic.ts

export const numbers = [1, 2, 3];

// ひとつずつ 2 倍にして、新しい配列を作る
export const doubled = numbers.map((n) => n * 2);

// numbers 自体はいっさい変わっていない