React에서 배열 사용하기 1 - 리스트 렌더링 (조회)
Array.map((it) => <Component key={it.id} {...it}/>)
1. React에서 리스트 렌더링 하기
세부 목표)
- 배열을 이용하여 React 에서 LIST 를 렌더링 해보고 개별적인 컴포넌트로 만들어보기
- 터미널
npm start
랜더링 : 화면에 표시한다.
일기 리스트를 랜더링 할 컴포넌트 src\DiaryList.js 생성.
- DiaryList.js
const DiaryList = () => {
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
</div>
);
};
export default DiaryList;
App.js 에도 등록 후, 임시 배열 데이터 생성 후 diaryList 라는 이름의 props 로 전달한다.
이후 DiaryList.js 에서 받기.
- App.js
import './App.css';
import DiaryEditor from './DiaryEditor';
import DiaryList from './DiaryList';
// 임시 배열 데이터
const dummyList = [
{
id: 1
, author: '송진성'
, content: '하이 1'
, emotion: 5
, created_date: new Date().getTime() // 현재 시간 기준 생성됨, getTime() : 시간을 밀리세컨트로 돌려줌
}
, {
id: 2
, author: '홍길동'
, content: '하이 2'
, emotion: 2
, created_date: new Date().getTime()
}
, {
id: 3
, author: '아무개'
, content: '하이 3'
, emotion: 1
, created_date: new Date().getTime()
}
]
function App() {
return (
<div className="App">
<DiaryEditor />
<DiaryList diaryList={dummyList}/>
</div>
);
}
export default App;
- DiaryList.js
const DiaryList = ({ diaryList }) => {
console.log(diaryList);
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
</div>
);
};
export default DiaryList;

본격적으로 배열을 LIST 형태로 랜더링 해본다.
- DiaryList.js
const DiaryList = ({ diaryList }) => {
console.log(diaryList);
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
<h4>{diaryList.length} 개의 일기가 있습니다.</h4>
<div>
{diaryList.map((it) => (
<div>
<div>작성자 : {it.author}</div>
<div>일기 : {it.content}</div>
<div>감정 : {it.emotion}</div>
<div>작성 시간(ms) : {it.created_date}</div>
</div>
))}
</div>
</div>
);
};
export default DiaryList;
diaryList 배열의 요소 하나하나가 it 변수로 들어온다.

defaultProps 기능을 통해 undefined 로 전달될 것 같은 props 들에 기본값 설정하기.
- App.js
import './App.css';
import DiaryEditor from './DiaryEditor';
import DiaryList from './DiaryList';
// 임시 배열 데이터
const dummyList = [
{
id: 1
, author: '송진성'
, content: '하이 1'
, emotion: 5
, created_date: new Date().getTime() // 현재 시간 기준 생성됨, getTime() : 시간을 밀리세컨트로 돌려줌
}
, {
id: 2
, author: '홍길동'
, content: '하이 2'
, emotion: 2
, created_date: new Date().getTime()
}
, {
id: 3
, author: '아무개'
, content: '하이 3'
, emotion: 1
, created_date: new Date().getTime()
}
]
function App() {
return (
<div className="App">
<DiaryEditor />
<DiaryList diaryList={undefined}/>
</div>
);
}
export default App;
- DiaryList.js
const DiaryList = ({ diaryList }) => {
console.log(diaryList);
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
<h4>{diaryList.length} 개의 일기가 있습니다.</h4>
<div>
{diaryList.map((it) => (
<div>
<div>작성자 : {it.author}</div>
<div>일기 : {it.content}</div>
<div>감정 : {it.emotion}</div>
<div>작성 시간(ms) : {it.created_date}</div>
</div>
))}
</div>
</div>
);
};
DiaryList.defaultProps = {
diaryList: []
}
export default DiaryList;

App.js 에서 undefined 를 다시 dummyList 로 수정하고 화면 콘솔을 보면 빨간색 글씨가 보인다.

리스트의 각각의 자식 요소들은 각각 고유한 key prop 를 받아야 한다는 내용이다. 고유한 key prop 을 적용해본다.
- DiaryList.js
const DiaryList = ({ diaryList }) => {
console.log(diaryList);
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
<h4>{diaryList.length} 개의 일기가 있습니다.</h4>
<div>
{diaryList.map((it) => (
<div key={it.id}>
<div>작성자 : {it.author}</div>
<div>일기 : {it.content}</div>
<div>감정 : {it.emotion}</div>
<div>작성 시간(ms) : {it.created_date}</div>
</div>
))}
</div>
</div>
);
};
DiaryList.defaultProps = {
diaryList: []
}
export default DiaryList;
배열의 고유한 id 를 자식 아이템 최상위 태그의 key 속성에 넣어준다.
만약 배열 안에 각 객체에 고유한 데이터가 없다면, map() 내장 함수의 콜백 함수에 2번째 파라미터인 idx (인덱스)를 사용하면 된다.
- 예시
<div>
{diaryList.map((it, idx) => (
<div key={idx}>
<div>작성자 : {it.author}</div>
<div>일기 : {it.content}</div>
<div>감정 : {it.emotion}</div>
<div>작성 시간(ms) : {it.created_date}</div>
</div>
))}
</div>
하지만, 배열의 인덱스를 key 로 사용하면 데이터를 수정하거나 삭제, 추가하며 인덱스들의 순서가 바뀔 때 리액트에서 문제가 발생할 수 있다. 따라서 고유한 id 가 존재한다면 인덱스보단 고유한 id 로 key 를 지정하는 것을 권장한다.
이번엔 diaryList 배열 데이터를 사용하여 렌더하는 아이템을 별도의 컴포넌트로 분할한다.
- DiaryList.js
import DiaryItem from "./DiaryItem";
const DiaryList = ({ diaryList }) => {
return (
<div className="DiaryList">
<h2>일기 리스트</h2>
<h4>{diaryList.length} 개의 일기가 있습니다.</h4>
<div>
{diaryList.map((it) => (
<DiaryItem key={it.id} {...it}/>
))}
</div>
</div>
);
};
DiaryList.defaultProps = {
diaryList: []
}
export default DiaryList;
- DiaryItem.js
const DiaryItem = ({ author, content, created_date, emotion, id }) => {
return (
<div className="DiaryItem">
<div className="info">
<span>작성자 : {author} | 감정점수 : {emotion}</span>
<br/>
<span className="date">{new Date(created_date).toLocaleString()}</span>
</div>
<div className="content">{content}</div>
</div>
);
};
export default DiaryItem;
new Date() 생성자의 매개변수로 밀리세컨드 데이터를 넣어주면, 밀리세컨드가 가진 시간 기준으로 Date 객체가 생성된다. Date 객체의 toLocaleString() 메서드를 사용하면 인간이 알아보기 좋은 형태로 바꿔준다.
마지막으로 DiaryList 와 DiaryItem 컴포넌트를 스타일링 한다.
- App.css
/* Editor */
.DiaryEditor {
border: 1px solid gray;
text-align: center;
padding: 20px;
}
.DiaryEditor input, textarea {
margin-bottom: 20px;
width: 500px;
padding: 10px;
}
.DiaryEditor textarea {
height: 150px;
}
.DiaryEditor select {
margin-bottom: 20px;
width: 300px;
padding: 10px;
}
.DiaryEditor button {
width: 500px;
padding: 10px;
cursor: pointer;
}
/* List */
.DiaryList {
border: 1px solid gray;
padding: 20px;
margin-top: 20px;
}
.DiaryList h2 {
text-align: center;
}
/* Item */
.DiaryItem {
background-color: rgb(240, 240, 240);
margin-bottom: 10px;
padding: 20px;
}
.DiaryItem .info {
border-bottom: 1px solid gray;
padding-bottom: 10px;
margin-bottom: 10px;
}
.DiaryItem .date {
color: gray;
}
.DiaryItem .content {
font-weight: bold;
margin-bottom: 30px;
margin-top: 30px;
}

참고강의 : https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%EB%A6%AC%EC%95%A1%ED%8A%B8#
한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 강의 - 인프런
개념부터 독특한 프로젝트까지 함께 다뤄보며 자바스크립트와 리액트를 이 강의로 한 번에 끝내요. 학습은 짧게, 응용은 길게 17시간 분량의 All-in-one 강의!, 리액트, 한 강의로 끝장낼 수 있어요.
www.inflearn.com