はじめに
Reactでは、配列からコンポーネントを生成する際にしばしばmap()が使用されます。
しかし、mapは配列を返すはずです。気持ち的には、forEachをつかってループごとにコンポーネントをreturnする方が直感に合っているような気がします。(それだと動かないですが)
もちろん「配列からコンポーネントをレンダーする」ことにおいてmap()を使用することに毎度疑問を抱きながら使っているわけではないのですが、なんとか納得したく色々遊んでみました。
※「配列をかえすんだから当たり前では?」と思った方は以降の内容を見てもよくわからないかもしれません、、、僕は当たり前には思えませんでした...
おさらい - map()とは -
map()は配列に対して使用できるメソッドで、配列の各要素を一つずつ取り出して関数を適用させ、その結果算出されたものを配列として返します。
const array = [1,2,3,4,5]
const doubleArray = array.map(num => num * 2)
console.log(doubleArray)
// [ 2, 4, 6, 8, 10 ]
不思議に思った点
「はじめに」にも記載しましたが、Reactではリストのレンダーにしばしばmap()が用いられます。
function App() {
const userArray = [
{
id: 1,
name: 'ange'
},{
id: 2,
name: 'lize'
},{
id: 3,
name: 'inui'
}
]
return (
<div>
{
userArray.map(user => (
<div>{user.id} - {user.name}</div>
))
}
</div>
{/*
このようになることを期待するし、実際にそうなる。
<div>
<div>1 - ange</div>
<div>2 - lize</div>
<div>3 - inui</div>
</div>
*/}
)
}
「map()でリストを一つずつとりだして、それを用いてdivが生成されるんでしょ」、では個人的にはしっくりきません。なぜならmap()は配列を返すので、以下のようになってしまうはずです。
<div>
{
// 配列が返るのでこうなるはず
[
<div>1 - ange</div>,
<div>2 - lize</div>,
<div>3 - inui</div>
]
}
</div>
すなわち、map()で処理する→リストが生成される と言う説明では少し飛躍しているように感じていました。
波括弧{}に配列を含めた時の挙動
しつこいですがmap()は配列を返すので、波括弧に配列を入れたときの挙動について調べたくなりました。
結論から言うとさきほど書いたコードの「配列が返るのでこうなるはず」の記述でもしっかり描画されます。
function App() {
return (
<div>
{
// JSXを含む配列を記述しても描画される
[ <div>1 - ange</div>, <div>2 - lize</div>, <div>3 - inui</div> ]
}
{/*
<div>
<div>1 - ange</div>
<div>2 - lize</div>
<div>3 - inui</div>
</div>
*/}
</div>
)
}
文字列を含む配列をいれると、それらが1行ずつ描画されます
function App() {
return (
<div>
{
['アンジュ','リゼ','戌亥']
}
</div>
{/*
<div>
アンジュ
リゼ
戌亥
</div>
*/}
)
}
ちなみに配列の代わりにオブジェクトを入れてみると怒られます
function App() {
return (
<div>
{
{id: 1, name: 'ange'}
}
</div>
// Uncaught Error: Objects are not valid as a React child
// (found: object with keys {id, name}). If you meant to render
// a collection of children, use an array instead.
)
}
配列を使えって書いてますね
波括弧に配列を入れた時の挙動が確認できたので、map()でコンポーネントが生成されるのも腑に落ちたのでした。
追記
関連記事にこちらの記事がありました。
僕と同じモヤモヤが出発点になってます。内部処理をのぞいているのでより詳しく把握できます。