map()을 보면, 처음 드는생각은
어?? 이거 자바스크립트 배열 내장메서드 아니야?
이걸로 리액트에서 뭘 어떻게할 수 있는데...
리액트에서 동적인 배열을 렌더링할 때,
map()을 이용하여 일반 데이터 배열을
리액트 엘리먼트로 이루어진 배열로 반환
실제로, 리액트에서 배열은 게시글, 리스트, 피드
등등을 표시하는 등에 자주 사용되기 때문에
무조건 알아둬야한다!!
아래의 예제를 보면서,
배열을 이용하여 리액트에서 List렌더링을 해보고,
개별적인 컴포넌트를 만들어보자!!
1. DiaryList.jsx
먼저, 일기리스트 컴포넌트를 작성할
DiaryList.jsx파일을 만들어준다.
2. App.js
그다음, dummyList를 만들어 DiaryList에
prop으로 데이터를 전달한 후,
그 데이터를 리스트 렌더링을 해보자!
3. DiaryEditor.jsx
아래는 useRef라는 Hook을 사용하여,
일기저장버튼을 클릭했을 때, 작성자와 일기가
정상적으로 입력이 되었는지 확인하고
입력이 되지않았다면 알람대신 focus로 알리는 것이다.
useRef 훅은 다시 한번 정리하여 포스팅할 예정이다 !!
4. DiaryList.jsx
DiaryList를 1번의 상태에서
map() 메서드를 이용하여 각각 리스트를
렌더링을 시켜보자!!
el은 diaryList 배열의 각각 객체 하나가 된다.
하지만, 이렇게만 해주고
콘솔창을 확인해보면, 아래와 같은 에러가
뜨는 것을 볼 수 있을 것이다.
위의 콘솔 에러는
dummyList에 있는 3개의 리스트들 안에 있는
자식요소들 (id, author, content, emotion, createdAt)은
반드시 고유한 key라는 prop을 받아야하는데 없기 때문에
위와 같은 에러가 발생하는 것이다.
⭐️ 여기서 map()에서 key가 필요한 이유를 설명할 것이다.
방법은 이론상으로는 매우 간단하다!!
고유한 id로 각각 리스트별로 key값을 주면된다!!
👉🏻 먼저, key를 줘야하는 이유가 뭘까??
이유는 리액트가 어떤 항목을 변경, 추가 또는 삭제를 할때
어떤 아이템이 변경되었는지 빠르게 식별하는 것을 도와주기 때문이다.
따라서 key는 고유한값이어야만 한다.
그래서... 그걸 어떻게하는데..??
위처럼 고유한값인 id를 key로 주어,
리액트 렌더링할 때 각각 리스트를 식별하여
렌더링을 할 수 있게 도와주는 것이다.
🚨 그럼 만약에 id가 없으면 어떡하나요...??
배열에 id같은 고유한 값이 없을때가 있을 수 도있다.
그럴때는 map메서드의 콜백함수에 두번째 파라미터로
idx를 key로 사용하는 방법이 있긴하다.
그렇게 사용해도 일단 문제가 사라지긴하지만
진짜 최후의최후의 수단으로 써야한다.
이유는 idx를 key로 사용하면
데이터를 수정, 삭제, 추가 등등을 하면
idx의 순서가 바뀌어버려 리액트에서 문제가 생길 수 있기 때문이다.
📌 map() 메서드에서의 key를 정리해보면,
- map에 key값이 없다면 중간에 값이 바뀌었을 때,
그 하위값들이 전부 변하기 때문에
key를 사용하여 key를 통해 추가, 삭제, 수정 등을 해야한다. - 고유 원소(ex: id)에 key가 있어야만 배열이 업데이트 될때
효율적으로 렌더링이 된다. - 만약 고유의 값으로 안쓰고 배열안에 중복되는 key가 있으면
렌더링시에 오류메세지가 콘솔에 나타나며,
컴포넌트의 state가 엉망이되거나, 의도하지 않은 방식으로 바뀔 수 있다.
🖇️ 배열을 DiaryItem으로 분할하기
만약 위의 일기장 예제에서
일기아이템들을 삭제, 수정하는 기능을 넣고 싶으면
원래의 DiaryList 컴포넌트는 리스트를 렌더링하려고
만든 컴포넌트였다.
하지만 이 컴포넌트에 삭제, 수정하는 기능들을 넣으면
컴포넌트의 고유기능을 잃어 매우 안좋은 컴포넌트가 된다.
따라서, 렌더링해야하는 아이템(작성자, 내용, 감정, 시간)을
별도의 컴포넌트로 분할을 해주어야한다.
1. DiaryList.jsx
위처럼 key는 그대로 el.id로 고유한 id값을 주었고,
일기 하나하나의 객체에 포함된 모든 데이터들을
스프레드연산자를 통하여 전달해주었다.
el이라는 객체에 포함된 모든 데이터가
DiaryItem에게 prop으로 전달된다.
2. DiaryItem.jsx
DiaryList에서 prop으로 받아온 데이터들을
컴포넌트의 매개변수로 받아서,
{}를 통하여 데이터들을 각각 렌더링시켜주었다.
3. App.css
위처럼 간단하게 css를 주어 보기좋게 만들어주면
끝이다!!!
결과를 보면,
이렇게 실제로도 자주 사용되는 리액트에서
동적인 배열을 렌더링해야 할때 map() 메서드를 사용하여
일반 데이터 배열을 리액트 엘리먼트로 이루어진 배열로
변환해주어, 렌더링되게 해주는걸 알아보았다.