결국은 기본인것 같다. 기본이 완벽해야 응용도 잘하는법!
정의는 단순하다, 배열을 받아 오름차순으로 접근해 Callback함수를 적용하여 새로운 배열을 반환하는것!
Array.prototype.map ( callbackfn [ , thisArg ] )
ex)
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);
//[2, 4, 6, 8, 10]
Map은 다양한 형태로 활용 되기도 한다.
1. 특정 값 꺼내기
const users = [ { name: 'YD', age: 22 }, { name: 'Bill', age: 32 }, { name: 'Andy', age: 21 }, { name: 'Roky', age: 35 }, ];
const ages = users.map(user => user.age); console.log(ages); // [22, 32, 21, 35]
결론적으로 users의 age만 꺼내게 된다.
2. 특정요소 재정의 하기
const users = [
{ name: 'YD', age: 22 },
{ name: 'Bill', age: 32 },
{ name: 'Andy', age: 21 },
{ name: 'Roky', age: 35 },
];
const newUsers = users.map(user => {
if (user.name === 'YD') {
return { ...user, age: 18 };
}
return { ...user };
});
console.log(newUsers);
// [{name: "YD", age: 18}, {name: "Bill", age: 32}, {name: "Andy", age: 21}, {name: "Roky", age: 35}]
[1,2,3,4,5]라는 배열을 받아서 map을 통해 li태그에 전달하여 리스트를 만들어내는 함수이다.
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')
);
JSX 문법인 중괄호를 이용해 map()을 인라인으로 바로 처리할 수도 있다.
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
)}
</ul>
);
}
그렇다면 React는 map함수를 돌릴때 어떻게 어떤항목을 추가/변경할지 식별할까?
Key값을 이용하여 식별한다! 보통은 data의 id 값으로 하기와 같이 배열 내부의 엘리먼트에 지정한다.
ex) 배열 내부의 엘리먼트 key 지정 예시
function ListItem(props) {
// 여기에는 key를 지정할 필요가 없습니다.
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// 배열 안에 key를 지정해야 합니다.
<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')
);
const todoItems = todos.map((todo) =>
<li key={todo.id}> // or <li key={index}>
{todo.text}
</li>
);
key값은 배열안에서만 고유하면 됩니다.
다른 배열간 map을 돌릴경우 각 배열 내에서의 key값만 고유하다면 key값이 동일해도 상관없습니다.
key는 컴포넌트에 직접적으로 전달할 수 없습니다. 전달받은 데이터의 id 값으로 사용해야 한다.
const content = posts.map((post) =>
<Post
key={post.id}
id={post.id}
title={post.title} />
);
!!!!key로 전달받은 post.key는 읽을수 없으며 전달받은 id 값을 key로 사용해야한다!!!!
결론부터 말하자면 이벤트가 발생하고 데이터가 변경되면
1. component가 Re-render된다.
2. 이때 index를 다시 mapping한다.
위의 2가지 과정에서 혼선이 발생하게 된다.
예를들어 하기의 코드를 보자
addItem: 추가버튼을 누르면 정국을 list 앞에 추가한다.
delItem: 삭제를 누르면 철수를 삭제한다.
현재 map에는 index를 Key로 사용하고 있다.
import React, {useEffect, useState} from 'react';
const Example = () => {
const [list, setList] = useState([
{name: '철수'},
{name: '영희'},
{name: '민수'},
])
const addItem = () => {
setList([{name: '정국'}, ...list]);
}
const delItem = () => {
setList(list.filter(l => l.name != "철수"));
}
return (
<>
{/* 추가 버튼과 삭제 버튼*/}
<input type="button" value="추가" onClick={addItem} />
<input type="button" value="삭제" onClick={delItem} />
<h2> Show Problem Example</h2>
{list.map((v, index) =>
/* div 태그의 key로 배열의 index 사용*/
<div key={index}> {v.name}, idx: {index} <input type="text" /> </div>
)}
</>
)
}
export default Example;
idx:0인 철수에 아래와 같이 데이터를 넣는다.
여기서 추가 버튼을 누른다면 정국이 추가되고 철수는 idx:1로 밀려나는 아래와 같은 그림이 예상된다.
하지만 실제로는 아래와 같이 작동한다.
왜이런 현상이 발생할까? 처음에 말했던 결론과 동일하다.
이벤트가 발생하고 component가 Re-rending 되면서 index가 다시 mapping 된다.
그 과정에서 정국이 idex 0 이 되면서 철수 데이터가 정국에게 mapping 된것이다.
Key값은 고유한 값으로 쓰자, Auto_increment된 Data.id가 대표적
forEach는 배열의 각 요소마다 한번씩 콜백함수를 실행한다.
map은 배열내 각 요소에 대해 콜백함수를 실행하고 결과를 모아 새로운 배열을 반환한다.
이 함수는 하기의 3가지 인자를 가지고 호출된다.
1. currentValue(배열의 값)
2. index
3. array(현재배열)
const arr = [1, 2, 3, 4, 5];
const mulArr = [];
arr.forEach(num => {
mulArr.push(num * 3);
});
console.log(mulArr); // [3, 6, 9, 12, 15]
forEach()는 밖으로 리턴값을 보내지 못한다.
let arr = [1,2,3,4,5];
let a = arr.forEach(function(value){
return value;
});
console.log(a); //undefined
let arr=[1,2,3,4,5];
let a = arr.map(function(value){
return value +1;
});
console.log(a); // [2,3,4,5,6]
둘의 가장 큰 차이는 Return값이다. 또한 forEach는 기존 Array를 변경하고 Map은 새로운 배열을 반환한다는것
출처
https://ko.reactjs.org/docs/lists-and-keys.html#gatsby-focus-wrapper 리액트 공식문서
https://medium.com/sjk5766/react-%EB%B0%B0%EC%97%B4%EC%9D%98-index%EB%A5%BC-key%EB%A1%9C-%EC%93%B0%EB%A9%B4-%EC%95%88%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-3ce48b3a18fb
https://dream-frontend.tistory.com/341
map으로 새로운 배열 리턴해준게 참 편리합니다