const numbers = [1,2,3,4,5];
const result = numbers.map(num => num*num);
console.log(result)
///[1,4,9,16,25]
위랑 똑같은 원리로 기존 배열로 컴포넌트로 구성된 배열을 생성 할 수도 있다.
const IternationSample = () => {
const names = ["눈사람", "얼음", "눈", "바람"];
const nameList = names.map((name) => <li>{name}</li>);
return <ul>{nameList}</ul>;
};
export default IternationSample;
//해당 컴포넌트를 app.js 에 연결해서 실행 시키면 'key'값이 없다고 뜬다.
리액트에서 key는 컴포넌트 배열을 렌더링했을때 어떤 원소에 변동이 있었는지 알아내려고 사용한다.
key값이 있다면 그 요소에 어떤 변화가 일어났는지 빠르게 알수있다.
앞서 만든 예제는 이런 고유 번호가 없다.
이때는 map함수에 전달되는 콜백함수의 인수인 index값을 사용한다
const IternationSample = () => {
const names = ["눈사람", "얼음", "눈", "바람"];
const nameList = names.map((name, index) => <li key={index}>{name}</li>);
///고유한 값인 인덱스로 키값을 주면 해당컴포넌트는 경고메세지가 사라지는걸 볼수 있다.
return <ul>{nameList}</ul>;
};
export default IternationSample;
index를 key로 사용하면 배열이 변경될때 효율적으로 렌더링 하지 못하기 떄문.
import { useState } from "react";
const IternationSample = () => {
const [names, setNames] = useState([
{ id: 1, text: "눈사람" },
{ id: 2, text: "얼음" },
{ id: 3, text: "눈" },
{ id: 4, text: "바람" },
]);
const [inputText, setInputText] = useState("");
const [nextId, setNextId] = useState(5);
const nameList = names.map((name) => <li key={name.id}>{name.text}</li>);
return <ul>{nameList}</ul>;
};
export default IternationSample;
예제를 다음과 같이 수정해본 결과 , 브라우저에 이전과 같은 결과가 나옴.
이번에는 map함수를 사용할때 key값을index대신 name.id로 지정해주었다.
이제 새로운 이름을 등록할 수 있는 기능을 구현해보자.
ul태그 상단에 input , button을 렌더링하고 input의 상태를 관리해보았다.
const IternationSample = () => {
const [names, setNames] = useState([
{ id: 1, text: "눈사람" },
{ id: 2, text: "얼음" },
{ id: 3, text: "눈" },
{ id: 4, text: "바람" },
]);
const [inputText, setInputText] = useState("");
const [nextId, setNextId] = useState(5);
const onChange = (e) => setInputText(e.target.value);
const nameList = names.map((name) => <li key={name.id}>{name.text}</li>);
return (
<>
<input value={inputText} onChange={onChange} />
<button>추가</button>
<ul>{nameList}</ul>;
</>
);
};
export default IternationSample;
그 다음으로 버튼을 클릭했을때 호출할 onClick함수를 선언하여 onClick이벤트로 설정하였다.
const IternationSample = () => {
const [names, setNames] = useState([
{ id: 1, text: "눈사람" },
{ id: 2, text: "얼음" },
{ id: 3, text: "눈" },
{ id: 4, text: "바람" },
]);
const [inputText, setInputText] = useState("");
const [nextId, setNextId] = useState(5);
const onChange = (e) => setInputText(e.target.value);
const onClick = () => {
const nextNames = names.concat({
id: nextId,
text: inputText,
});
setNextId(nextId + 1);//nextId값에 1을 더해준다
setNames(nextNames);//names 값을 업데이트한다
setInputText("");//InputText를 비운다.
};
const nameList = names.map((name) => <li key={name.id}>{name.text}</li>);
return (
<>
<input value={inputText} onChange={onChange} />
<button onClick={onClick}>추가</button>
<ul>{nameList}</ul>;
</>
);
};
export default IternationSample;
배열에 새항목을 추가할때 push 대신 concat을 사용했다 pusy와 concat의 차이는 기존 상태를 그냥 두냐 변하게하느냐의 차이이다 리액트에서는 상태를 업데이트시 기존상태를 그대로 두면서 새로운 값의 상태로 설정해야한다. (불변성 유지)
onClick함수에서 새로운 항목을 추가할떄 객체의 id값은 nextId를 사용하도록하고 , 클릭될떄마다 1씩 올라가도록 구현했다. 또한 button이 클릭될때 기존의 input 내용이 비워지도록 구현했다.