강의 실습/한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지

React에서 배열 사용하기 1 - 리스트 렌더링 (조회)

Jint 2024. 1. 15. 23:23

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;

 

임시 배열 데이터 3개 잘 받음


본격적으로 배열을 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 변수로 들어온다.

 

배열을 LIST 형태로 랜더링


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;

 

defaultProps 이용한 props 기본값 설정 결과


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