본문 바로가기
Framework/react

[리액트] map으로 배열 렌더링하기

by 딸기뚜왈기 2024. 6. 13.



 

[React] map( )을 이용한 배열 렌더링 (feat.일기장)

💡map() 이란? 자바스크립트 배열 내장함수 리액트에서 동적인 배열을 렌더링해야 할 때는 자바스크립트 배열 내장함수인 map()을 사용하여 일반 데이터 배열을 리액트 엘리먼트로 이루어진 배열

velog.io

 

 

import "./styles.css";
import Name from "./Name.js";
import Age from "./Age.js";
import React, { Component } from "react";
import NameAge from "./NameAge";
import DiaryList from "./DiaryList";

const info = [
  {
    id: 1,
    first: "D",
    last: "Him",
  },
  { id: 2, first: "G", last: "Min" },
];

const dummyList = [
  {
    id: 1,
    author: "hyun",
    content: "첫번째",
    emotion: 1,
    created_date: new Date().getTime(),
  },
  {
    id: 2,
    author: "jeong",
    content: "두번째",
    emotion: 2,
    created_date: new Date().getTime(),
  },
  {
    id: 3,
    author: "react",
    content: "3번째",
    emotion: 3,
    created_date: new Date().getTime(),
  },
];

class App extends Component {
  render() {
    return (
      <div>
        <Name first="S" last="Lee" />
        <Age age="20" />
        <NameAge nameAge={info} />
        <DiaryList diaryList={dummyList} />
      </div>
    );
  }
}

export default App;

 

 

import React from "react";

const NameAge = ({ nameAge }) => {
  return (
    <div className="NameAge">
      <h2>자기개</h2>
      <h4>{nameAge.length}개의 일기가 있습니다</h4>
      <div>
        {nameAge.map((it) => (
          <div>
            <div>성: {it.first}</div>
            <div>이름: {it.last}</div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default NameAge;

 

 

it은 diaryList배열의 하나하나의요소가 들어오는거라 하나의 객체가 id이 된다.(객체 점표기법으로 접근할 수 있다.)

 

import React from "react";

const DiaryList = ({ 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>
        ))}
    </div>
    </div>
  );
};

export default DiaryList;
 

 

 

배열의 요소가 리스트형태로 렌더링된것을 확인할 수 있다.

 

 

defaultProps사용하는 방법

근데 App.js에서 <DiaryList diaryList={dummyList}/>로 props값을 전해줘야하는데, <DiaryList diaryList={undefined}/>로 주었다면?

->undefined으로부터 length라는 프로퍼티를 읽어올수가없다는 라는 에러가 나온다
-> 이럴땐, 저번에 배운 defaultProps를 사용하면 된다!!

 

defaultProps
= undefined으로 전달될거같은 props들의 기본값(=초기값)을 설정해주는 기능

 

 


class App extends Component {
  render() {
    return (
      <div>
        <Name first="S" last="Lee" />
        <Age age="20" />
        <NameAge nameAge={info} />
        <DiaryList diaryList={undefined} />
      </div>
    );
  }
}

export default App;

 

import React from "react";

const DiaryList = ({ 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>
        ))}
      </div>
    </div>
  );
};

DiaryList.defaultProps = {
  diaryList: [],
};

export default DiaryList;

 

map()에서 Key가 필요한 이유

다시 props에 dummyList 값을 넣어줘서 콘솔을 확인하면 아래와같은 에러가 뜨는것을 확인할수있다.

 

dummyList에 만든 3개의 리스트들 안에 있는 자식요소들(id,author,content,emotion,created_date)은 반드시 고유한 key라는 prop을 받아야 한다 라는 에러이다

 

<divkey={it.id}>
   <div>작성자: {it.author}</div>  
   <div>내용: {it.content}</div>
   <div>감정: {it.emotion}</div>
   <div>작성시간(ms): {it.created_date}</div>
</div>

 

 

지금사용하는 고유한값인 id를이용하여 key를 주었다.

{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>
))}

 

 

 

만약 배열의 원소에 고유한값이 없을 경우에는,

map내장함수의 콜백함수에 두번째 파라미터에 idx를 key로 사용하는 방법이 있다.
(*index란? 몇번째요소를순회하고있는지를알려주는값)
배열 요소들의 인덱스는 고유하므로 키로 사용해도 일단 문제가 사라진다.
하지만 배열의 인덱스를 사용하게되면, 데이터를 수정,삭제,추가해서 인덱스의 순서가 바뀌어버릴때 리액트에서 문제가 생길 수 있다.
그래서, 고유한 id를 갖고있으면 인덱스(idx)를 사용하지말고 고유한 id로 key를 지정하는게 가장 좋다

 

map()에서 Key정리

  • Map에 key값이 없다면 중간의 값이 바뀌었을때 그 하위 값들이 전부 변하기 때문인다. key값을 사용한다면 key를 이용해 중간의 값을 추가하게 된다.
  • 고유 원소에 key 가 있어야만 배열이 업데이트 될 때 효율적으로 렌더링
  • 수정되지 않는 기존의 값은 그대로 두고 원하는 곳에 내용을 삽입하거나 삭제하기 때문
  • 만약에 배열안에 중복되는 key 가 있을 때에는 렌더링시에 오류메시지가 콘솔에 나타나게 되며, 업데이트가 제대로 이루어지지 않게 된다.

 

배열을 DiaryItem으로 분할하기

diaryList배열에서 map메서드를 통하여 리스트아이템들을 화면에 렌더링을 하고있는데, 프로그램에서 일기아이템들을 삭제,수정하는 기능들도 넣고싶다.
원래는 DiaryList컴포넌트는 리스트를 렌더링하려고 컴포넌트를 만들었는데, 삭제,수정하는 기능들까지넣으면 매우 안좋아진다.(=컴포넌트의 고유기능을 잃는느낌)
그래서 diaryList배열을 사용해서 렌더하는 아이템(작성자,일기,감정,시간)을 별도의 컴포넌트인 DiaryItem으로 분할한다.

 

 

 

DiaryItem은 일기데이터들을 렌더링을해야하기때문에(=리스트아이템이기때문에) key={it.id}를 주었다.
또, 일기 하나 객체에 포함된 모든 데이터를 스프레드연산자를 통해서 전달해주었다. 그러면 it이라는 객체에 포함된 모든데이터가 DiaryItem에게 prop으로 전달된다.

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 className="content">내 용 : {content}</div>
      </div>
    </div>
  );
};

export default DiaryItem;

 

import React from "react";
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>
  );
};

export default DiaryList;

 

 

https://codesandbox.io/p/sandbox/bold-worker-2wnz9g

 

 

[React] map( )을 이용한 배열 렌더링 (feat.일기장)

💡map() 이란? 자바스크립트 배열 내장함수 리액트에서 동적인 배열을 렌더링해야 할 때는 자바스크립트 배열 내장함수인 map()을 사용하여 일반 데이터 배열을 리액트 엘리먼트로 이루어진 배열

velog.io