import React from "react";
const IterationSample = () => {
return (
<ul>
<li>눈사람</li>
<li>얼음</li>
<li>눈</li>
<li>바람</li>
</ul>
);
};
export default IterationSample;
<li>
태그가 반복된다. → 반복적인 내용을 효율적으로 보여 주고 관리하는 방법 배운다.
자바스크립트 배열 객체의 내장 함수인 map 함수를 사용하여 반복되는 컴포넌트를 렌더링할 수 있다. map 함수는 파라미터로 전달된 함수를 사용해서 배열 내 각 요소를 원하는 규칙에 따라 변환한 후 그 결과로 새로운 배열을 생성한다.
arr.map(callback, [thisArg])
var processed = numbers.map(function(num){return num*num;});
를 Arrow Function으로 표현하면
var processed = numbers.map(num => num * num);
import React from "react";
const IterationSample = () => {
const names = ["눈사람", "얼음", "눈", "바람"];
const nameList = names.map((name) => <li>{name}</li>); // DOM 요소
return <ul>{nameList}</ul>;
};
export default IterationSample;
map 함수에서 JSX를 작성할 때는 DOM 요소와 컴포넌트 둘 다 사용 가능하다.
const nameList = names.map((article) =>
// 컴포넌트
<Article
title = {article.title}
writer = {article.writer}
key = {article.id}
/>
);
"key" prop이 없다는 경고 메시지를 표시했다.
리액트에서 key는 컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었는지 알아내려고 사용한다. 예를 들어 유동적인 데이터를 다룰 때는 원소를 새로 생성할 수도, 제거할 수도, 수정할 수도 있다.
key값이 없을 때는 virtual DOM을 비교하는 과정에서 리스트를 순차적으로 비교하면서 변화를 감지한다. key가 있다면 이 값을 사용하여 어떤 변화가 일어났는지 더욱 바르게 알아낼 수 있다.
key 값을 설정할 때는 map 함수의 인자로 전달되는 함수 내부에서 컴포넌트 props를 설정하듯이 설정한다. key 값은 언제나 유일해야 한다. 따라서 데이터가 가진 고윳값을 key 값으로 설정한다.
import React from "react";
const IterationSample = () => {
const names = ["눈사람", "얼음", "눈", "바람"];
const nameList = names.map((name, index) => <li key={index}>{name}</li>);
return <ul>{nameList}</ul>;
};
export default IterationSample;
고유한 값이 없을 때만 index 값을 key로 사용해야 한다. index를 key로 사용하면 배열이 변경될 때 효율적으로 리렌더링하지 못한다.
동적인 배열을 렌더링해보자!
유동적인 데이터 렌더링
초기 상태 설정하기 → 데이터 추가 기능 구현하기 → 데이터 제거 기능 구현하기
useState
를 사용하여 상태를 설정한다. 세 가지 상태를 사용할 건데,
위의 예제에서는 단순히 문자열로 이루어진 배열을 만들었지만, 이번에는 객체 형태로 이루어진 배열을 만들 것!
import React, { useState } from "react";
const IterationSample = () => {
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); // 새로운 항목을 추가할 때 사용할 id
const nameList = names.map((name) => <li key={name.id}>{name.text}</li>);
return <ul>{nameList}</ul>;
};
export default IterationSample;
import React, { useState } from "react";
const IterationSample = () => {
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); // 새로운 항목을 추가할 때 사용할 id
const onChange = (e) => setInputText(e.target.value);
const onClick = () => {
const nextNames = names.concat({
id: nextId, // nextId 값을 id로 설정
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}></input>
<button onClick={onClick}>추가</button>
<ul>{nameList}</ul>;
</>
);
};
export default IterationSample;
각 항목을 더블클릭했을 때 해당 항목이 화면에서 사라지는 기능을 구현해보자.
불변성을 유지하면서 업데이트 해주어야하고, 불변성을 유지하면서 배열의 특정 항목을 지울 때는 배열의 내장 함수 filter를 사용한다.
filter 함수를 사용하면 배열에서 특정 조건을 만족하는 원소들만 쉽게 분류할 수 있다.
const numbers = [1, 2, 3, 4, 5, 6];
const biggerThanThree = numbers.filter( number => number > 3);
결과는 [4, 5, 6]
이 나온다.
const numbers = [1, 2, 3, 4, 5, 6];
const biggerThanThree = numbers.filter( number => number != 3;
결과는 [1, 2, 4, 5, 6]
이 나온다.
import React, { useState } from "react";
const IterationSample = () => {
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); // 새로운 항목을 추가할 때 사용할 id
const onChange = (e) => setInputText(e.target.value);
const onClick = () => {
const nextNames = names.concat({
id: nextId,
text: inputText,
});
setNextId(nextId + 1);
setNames(nextNames);
setInputText("");
};
const onRemove = (id) => {
const nextNames = names.filter((name) => name.id != id); // 클릭한 id가 아닌 것들만 분류해서 배열을 만든다.
setNames(nextNames);
};
const nameList = names.map((name) => (
<li key={name.id} onDoubleClick={() => onRemove(name.id)}>
{name.text}
</li>
));
return (
<>
<input value={inputText} onChange={onChange}></input>
<button onClick={onClick}>추가</button>
<ul>{nameList}</ul>;
</>
);
};
export default IterationSample;
컴포넌트 배열을 렌더링할 때는 key 값 설정에 항상 유의해야 한다. 또 key 값은 언제나 유일해야 한다. key 값이 중복된다면 렌더링 과정에서 오류가 발생한다.
상태 안에서 배열을 변형할 때는 배열에 직접 접근하여 수정하는 것이 아니라 concat, filter 등의 배열 내장 함수를 사용하여 새로운 배열을 만든 후 이를 새로운 상태로 설정해 주어야 한다.