[Describing The UI] Rendering Lists

Goonco·2024년 1월 10일
0

🎈 Learn React

목록 보기
7/12
post-thumbnail

🍺 Rendering data from arrays


다음과 같은 반복되는 markup을 보다 효율적으로 JSX로 나타낼 수 있을까?

<ul>
  <li>list item 1</li>
  <li>list item 2</li>
  <li>list item 3</li>
  <li>list item 4</li>
  <li>list item 5</li>
</ul>

주목해야할 점은 기본적인 markup은 <li>로 동일하나 그 안의 내용, 즉 데이터만 변한다는 사실이다. 따라서 React는, 이와 같이 반복되는 데이터의 경우, 이들을 JavaScript object나 array에 저장하고 map()filter()를 통해 순회하며 rendering하는 방식을 사용한다.

const contents = [
  'list item 1',
  'list item 2',
  'list item 3',
  'list item 4',
  'list item 5',
];

export default function List() {
  const listItems = contents.map(content =>
    <li>{content}</li>
  );
  return <ul>{listItems}</ul>;
}

🍸 Filtering arrays of items


위의 예제에서는 map()만을 사용했으나, 데이터들 중 특정 데이터들만 render해야할 경우 filter()를 이용할 수 있다.

const people = [{
  id: 0,
  name: 'Creola Katherine Johnson',
  profession: 'mathematician',
}, {
  id: 1,
  name: 'Mario José Molina-Pasquel Henríquez',
  profession: 'chemist',
}, {
  id: 2,
  name: 'Mohammad Abdus Salam',
  profession: 'physicist',
}, {
  name: 'Percy Lavon Julian',
  profession: 'chemist',  
}, {
  name: 'Subrahmanyan Chandrasekhar',
  profession: 'astrophysicist',
}];

위와 같은 데이터가 존재하며, 해당 데이터들 중 profession이 'chemist'인 항목만 출력해야 한다고 하자. 이 경우 filter()map()을 함께 활용한다.

import { people } from './data.js';

export default function List() {
  const chemists = people.filter(person =>
    person.profession === 'chemist'
  );
  const listItems = chemists.map(person =>
    // ...markup
  );
  return <ul>{listItems}</ul>;
}

🍷 Keeping list items in order with key


위 예시들을 그대로 이용할 경우, console창에 다음과 같은 알림창이 발생한다.

⛔ Warning: Each child in a list should have a unique “key” prop.

해당 Warning을 해결하기 위해선 아래와 같은 구현이 필요하다.

<li key={person.id}>...</li>

🚨 JSX elements directly inside a map() call always need keys!

명심하자. map()을 통해 반복적으로 render되는 JSX는 반드시 key를 전달해야 한다. Key들은 React에게 어떤 array item과 어떤 component가 대응되는지 알려주는 역할을 한다. 이는, array item이 수정으로 인해 변할 때, DOM을 올바르게 업데이트되도록 한다.


• Displaying several DOM nodes for each list item

map()내에서 하나 이상의 DOM node를 render하며 동시에 하나의 JSX 태그로 묶여져 있지 않다면 <Fragment> syntax를 이용한다.

const listItems = people.map(person =>
  <Fragment key={person.id}>
    <h1>{person.name}</h1>
    <p>{person.bio}</p>
  </Fragment>
);

이때, <>...</> syntax를 사용할 경우 key를 전달할 수 없으니 주의하자.


• Where to get your key

어디서 key를 가져올 수 있을까?

  • Data from a database : 가장 좋은 방법은 데이터 베이스 자체에 ID와 같은 unique한 속성을 보유하고 있는 것 이다.

  • Locally generated data : crypto.randomUUID()uuid와 같은 package를 이용하여 unique한 값을 생성하자.


• Rules of keys

  • Keys must be unique among siblings : 다시말해, 다른 array간에는 동일한 key를 가져도 상관없다.

  • Keys must not change : Do Not generate them while rendering!


• Why does React need keys?

앞서 말했듯, 불변하는 데이터에 대해서는 key의 의미가 크게 존재하지 않는다. 예를 들어, 당신이 이름없는 파일들을 관리한다고 생각하자. 최초에는 각 파일들을, 첫번째 파일, 두번째 파일, ...과 같이 순서로 구분할 수 있다. 그러나, 첫 파일이 삭제된 경우, 두번째 파일이 첫번째 파일로, 세번째 파일이 두번째 파일로, ... 변화하게 된다. 따라서, 계속해서 수정되는 파일의 집합의 경우 각 파일에 대한 이름, 즉, key가 필요하다.

🚨 Array item의 index를 key로 사용하는 것은 바람직하지 않다. 위에서 말한 것처럼 수정 시 각 index는 변하게 되므로 불변하는 값을 필요로 하는 key에는 적합하지 않다. 비슷하게 Math.random() 역시 바람직하지 않다. 매 render마다 Math.random()의 값이 변할 뿐만 아니라, unique함을 보장하지도 않는다.

🚨 Component는 key를 prop으로 전달받지 않는다. 따라서 id 값이 필요한 경우 <Profile key={id} userId={id} />와 같이 독립적으로 전달받아야 한다.

profile
이끼 끼지 않기 💦

0개의 댓글