React 9. Rendering Lists

뚜루미·2024년 3월 1일

React

목록 보기
9/39
post-thumbnail

데이터 컬렉션에서 여러 유사한 컴포넌트를 표시하려는 경우가 많습니다. JavaScript 배열 메소드를 사용하여 데이터 배열을 조작할 수 있습니다. fliter()map() 을 사용하여 데이터 배열을 컴포넌트 배열로 변환할 수 있습니다.

Rendering data from arrays

다음과 같은 컨텐츠 목록이 있다고 가정해 보겠습니다.

<ul>
  <li>Creola Katherine Johnson: mathematician</li>
  <li>Mario José Molina-Pasquel Henríquez: chemist</li>
  <li>Mohammad Abdus Salam: physicist</li>
  <li>Percy Lavon Julian: chemist</li>
  <li>Subrahmanyan Chandrasekhar: astrophysicist</li>
</ul>

해당 목록 항목 간의 유일한 차이점은 해당 내용과 데이터입니다. 인터페이스를 구축할 대 댓글 목록부터 프로필 이미지 갤러리까지 다양한 데이터를 사용하여 동일한 컴포넌트의 여러 인스턴스를 표시해야 하는 경우가 많습니다. 이러한 상황에서는 해당 데이터를 JavaScript 개체 및 배열에 저장하고 map()filter() 와 같은 메소드를 사용하여 컴포넌트를 렌더링할 수 있습니다.

다음은 배열에서 listItems 를 생성하는 짧은 예제입니다.

// 1. 데이터를 배열로 이동합니다.
const people = [
  'Creola Katherine Johnson: mathematician',
  'Mario José Molina-Pasquel Henríquez: chemist',
  'Mohammad Abdus Salam: physicist',
  'Percy Lavon Julian: chemist',
  'Subrahmanyan Chandrasekhar: astrophysicist'
];

// 2. 멤버 people 를 새로운 JSX 노드 배열로 매핑합니다.
const listItems = people.map(person => <li>{person}</li>);

// 3.listItems을 <ul>로 래핑된 컴포넌트를 반환합니다.
return <ul>{listItems}</ul>;

Filtering arrays of items

데이터는 보다 구조화될 수 있습니다.

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',
}];

직업이 ‘chemist’인 사람만 표시하는 방법을 원한다고 가정해보겠습니다. JavaScript의 filter() 메소드를 사용하여 해당 사람들만 반환할 수 있습니다. 이 메소드는 listItems을 가져와 테스트(truefalse를 반환하는 함수)를 수행하고 통과한 아이템들로 구성된 새로운 배열을 반환합니다.

profession이 ‘chemist’인 항목을 원한다면, 테스트 함수를 (person) => person.profession === 'chemist' 와 같이 작성하면 됩니다.

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

export default function List() {
	// 1. filter()를 사용하여 person.profession === 'chemist'인 
	// 항목들로 구성된 새로운 배열을 생성합니다.
  const chemists = people.filter(person =>
    person.profession === 'chemist'
  );
	// 2. chemists을 매핑합니다.
  const listItems = chemists.map(person =>
    <li>
      <img
        src={getImageUrl(person)}
        alt={person.name}
      />
      <p>
        <b>{person.name}:</b>
        {' ' + person.profession + ' '}
        known for {person.accomplishment}
      </p>
    </li>
  );
	// 3. 마지막으로 컴포넌트에서 listItems를 반환합니다.
  return <ul>{listItems}</ul>;
}

🚨 화살표 함수 사용시 유의 사항

화살표 함수는 암시적으로 바로 뒤(=>)에 표현식을 반환하므로 return 명령문이 필요하지 않습니다.

const listItems = chemists.map(person =>
  <li>...</li> // Implicit return!
);

하지만 뒤에 중괄호( => { )가 오면 retunr을 명시적으로 작성해야 합니다.

const listItems = chemists.map(person => { // Curly brace
  return <li>...</li>;
});

=> { 가 포함된 화살표 함수는 “block body”를 갖는다고 합니다. 한 줄 이상의 코드를 작성할 수 있지만 return 명령문을 직접 작성해야 합니다. 작성하지 않으면 아무것도 반환되지 않습니다.

Keeping list items in order with key

아래와 같은 오류가 출력될 수 있습니다.

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

각 배열 항목에 해당 배열의 다른 항목 중에서 key (고유하게 식별하는 문자열 또는 숫자)를 제공해야 합니다 .

 map() 호출 내부의 JSX 요소는 항상 키가 있어야 합니다.

키는 각 컴포넌트가 어떤 배열 항목에 해당하는지 React에게 알려주므로 나중에 일치시킬 수 있습니다. 배열 항목이 이동되거나 삽입되거나 삭제될 수 있는 경우 이는 중요합니다. 질 선택한 key 는 React가 정확히 무슨 일이 일어났는지 추론하고 DOM 트리를 올바르게 업데이트하는 데 도움이 됩니다.

키를 즉시 생성하는 대신 데이터에 포함해야 합니다.

// App.js
import { people } from './data.js';
import { getImageUrl } from './utils.js';

export default function List() {
  const listItems = people.map(person =>
    <li key={person.id}>
      <img
        src={getImageUrl(person)}
        alt={person.name}
      />
      <p>
        <b>{person.name}</b>
          {' ' + person.profession + ' '}
          known for {person.accomplishment}
      </p>
    </li>
  );
  return <ul>{listItems}</ul>;
}

// data.js
export const people = [{
  id: 0, // Used in JSX as a key
  name: 'Creola Katherine Johnson',
  profession: 'mathematician',
  accomplishment: 'spaceflight calculations',
  imageId: 'MK3eW3A'
}, {
  id: 1, // Used in JSX as a key
  name: 'Mario José Molina-Pasquel Henríquez',
  profession: 'chemist',
  accomplishment: 'discovery of Arctic ozone hole',
  imageId: 'mynHUSa'
}, {
  id: 2, // Used in JSX as a key
  name: 'Mohammad Abdus Salam',
  profession: 'physicist',
  accomplishment: 'electromagnetism theory',
  imageId: 'bE7W1ji'
}, {
  id: 3, // Used in JSX as a key
  name: 'Percy Lavon Julian',
  profession: 'chemist',
  accomplishment: 'pioneering cortisone drugs, steroids and birth control pills',
  imageId: 'IOjWm71'
}, {
  id: 4, // Used in JSX as a key
  name: 'Subrahmanyan Chandrasekhar',
  profession: 'astrophysicist',
  accomplishment: 'white dwarf star mass calculations',
  imageId: 'lrWQx8l'
}];

Displaying several DOM nodes for each list item

각 항목이 하나가 아닌 여러 개의 DOM 노드를 렌더링해야 하는 경우 짧은 <>...</> Fragment 구문에서는 키를 전달할 수 없으므로 이를 단일 <div>로 그룹화하거나 약간 더 길고 더 명시적인 <Fragment>구문을 사용해야 합니다.

import { Fragment } from 'react';

// ...

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

Fragment는 DOM에서 사라지고, <h1>, <p>, <h1>, <p>등의 단순 목록이 생성됩니다.

Where to get your key

다양한 데이터 소스는 다양한 키 소스를 제공합니다.

  • 데이터베이스의 데이터 : 데이터가 데이터베이스에서 오는 경우 본질적으로 고유한 데이터베이스 키/ID를 사용할 수 있습니다.
  • 로컬에서 생성된 데이터 : 데이터가 로컬에서 생성되고 유지되는 경우 항목을 생성할때 증가 카운터나, crypto.randomUUID(), uuid 같은 패키지를 사용하여 생성할 수 있습니다.

Rules of keys

키는 형제간에 고유해야 합니다. 그러나 다른 배열의 JSX 노드에 동일한 키를 사용하는 것은 가능합니다.

키는 변경되면 안되므로 렌더링하는 동안 키를 생성하면 안됩니다.

Why does React need keys?

데스크탑에 있는 파일에 이름 대신 첫 번째 파일, 두 번째 파일 등 순서에 따라 파일에 참조할 수 있다고 가정해보겠습니다. 익숙해질 수는 있지만 파일을 삭제하면 혼란스러워집니다. 폴더에 있는 파일 이름과 배열에 있는 JSX 키가 비슷한 역할을 합니다. 형제간의 고유하게 식별할 수 있도록 해주고 잘 선정된 키는 배열 내의 위치보다 더 많은 정보를 제공합니다. 재정렬로 인해 위치가 변경되더라고 키는 React로 하여금 항목을 식별할 수 있게 합니다.

배열에 있는 항목의 인덱스를 키로 사용하는 경우 항목이 삽입되거나 삭제되거나 재정렬 하는 경우 항목을 렌더링하는 순서가 시간이 지남에 따라 달라집니다. 키로 인덱스를 지정하면 종종 버그롤 초래합니다.

마찬가지로 key={Math.random()} 를 사용하여 키를 즉시 생성하면 안됩니다. 이렇게 하면 렌더링간 키가 일치하지 않으므로 모든 컴포넌트와 DOM이 매번 다시 생성됩니다. 속도가 느릴뿐만 아니라 목록 항목 내에서 사용자 입력이 손실됩니다. 대신 데이터를 기반으로 안정적인 ID를 사용해야 합니다.

컴포넌트는 key를 props로 받지 않습니다. React 자체에서만 힌트로 사용됩니다. 컴포넌트에 ID가 필요한 경우 별도의 props로 전달해야 합니다. <Profile key={id} userId={id} />.

0개의 댓글