本文へスキップ
配列の map

Part 0 · React の前に

4 / 64

配列の 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 は元の配列に手を加えません。 別の配列を新しく作って返すだけです。

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

map-basic.ts

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

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

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

実際のデータは、たいていオブジェクトの配列です。 そこから必要なものだけを取り出したり、別の形に整えたりするのにも 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 の兄弟たち

map と同じ形で使える仲間がいます。この 3 つは、React でも map と同じくらい出てきます。いま覚えなくても構いませんが、何が返るかだけ見ておいてください。

同じ配列に、4 つを当ててみる

返ってきたものの形に注目

scores = [1, 2, 3, 4, 5]

  • scores.map((n) => n * 2)[2,4,6,8,10]数は変わらない
  • scores.filter((n) => n > 2)[3,4,5]数が減る
  • scores.find((n) => n > 2)3配列ではない
  • scores.reduce((sum, n) => sum + n, 0)151 つにまとまる

違いは「何が返るか」です。

  • map同じ数の配列。作り変える
  • filter減った配列。選び出す
  • find配列ではなく 1 つの値。探す
  • reduce1 つにまとめた値。畳む

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

map-friends.ts

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

// map … 全部を作り変える。数は変わらない
export const doubled = scores.map((n) => n * 2); // [2, 4, 6, 8, 10]

// filter … 条件に合うものだけ残す。数が減る
export const big = scores.filter((n) => n > 2); // [3, 4, 5]

// find … 条件に合う最初の 1 つ。配列ではなく値が返る
export const firstBig = scores.find((n) => n > 2); // 3

// reduce … ひとつの値にまとめる。第 2 引数は始めの値
export const total = scores.reduce((sum, n) => sum + n, 0); // 15

// どれも元の配列は変えない
export const original = scores; // [1, 2, 3, 4, 5]

理解できたか確かめる

確認クイズ

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);

この章のまとめ

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

map-basic.ts

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

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