[React] UI 표현하기 - 리스트 렌더링

Gyuhan Park·2024년 1월 31일
0

공식문서

목록 보기
7/10

[ 요약 ]

  • array.map() : 동일한 컴포넌트 구조에 서로 다른 데이터 렌더링
  • array.filter() : 원하는 조건에 해당하는 항목만 필터링
  • key 를 사용해서 리스트 항목을 순서대로 유지
  • 위치가 변경되더라도 생명주기 내내 해당 항목을 key로 식별 가능
  • 형제 항목 간에 항목을 고유하게 식별
  • index 로 key값을 대신할 경우 배열의 순서가 바뀌었을 때 렌더링 순서 변경 위험
  • key={Math.random()} 과 같이 즉석에서 key 생성 ❌

[ 학습 내용 ]

  • JavaScript의 map()을 사용하여 배열을 컴포넌트로 렌더링하는 방법
  • JavaScript의 filter()를 사용하여 특정 컴포넌트만 렌더링하는 방법
  • React에서 Key가 필요한 때와 이유

📘 배열을 데이터로 렌더링하기

리스트 항목의 유일한 차이점 : 데이터
서로 다른 데이터를 사용하여 동일한 컴포넌트의 여러 인스턴스를 표시해야하는 경우
해당 데이터를 Javascript 객체와 배열에 저장하고 배열 메서드를 사용하여 해당 객체에서 컴포넌트 리스트 렌더링 가능

  1. 데이터를 배열로 이동
  2. people의 요소를 새로운 JSX 노드 배열인 listItems에 매핑
  3. <ul>로 래핑된 컴포넌트의 listItems 반환
const people = [
  'Creola Katherine Johnson: mathematician',
  'Mario José Molina-Pasquel Henríquez: chemist',
  'Mohammad Abdus Salam: physicist',
  'Percy Lavon Julian: chemist',
  'Subrahmanyan Chandrasekhar: astrophysicist'
];

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

📘 배열의 항목들을 필터링하기

JavaScript의 filter() 메서드를 사용하여 해당하는 사람만 반환
array.filter() : boolean을 반환하는 함수를 인수로 받아 true가 반환된 항목만 있는 새로운 배열 반환

  1.  person.profession === 'chemist'로 필터링해서 “chemist”로만 구성된 새로운 배열 chemists 생성
  2. 이제 chemists를 매핑
  3. 마지막으로 컴포넌트에서 listItems를 반환
import { people } from './data.js';
import { getImageUrl } from './utils.js';

export default function List() {
  const chemists = people.filter(person =>
    person.profession === 'chemist'
  );
  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>
  );
  return <ul>{listItems}</ul>;
}

🚨 주의하세요!

화살표 함수는 암시적으로 => 바로 뒤에 식을 반환하기 때문에 return 문 필요 ❌

const listItems = chemists.map(person =>
  <li>...</li> // 암시적 반환!
);

하지만 => 뒤에 { 중괄호가 오는 경우 return을 명시적으로 작성해야함

const listItems = chemists.map(person => { // 중괄호
  return <li>...</li>;
});

=> { 를 표현하는 화살표 함수 : “block body”를 가지고 있다고 표현
return문을 작성하지 않으면 아무것도 반환되지 않음

📘 key를 사용해서 리스트 항목을 순서대로 유지하기

각 배열 항목에 다른 항목 중에서 고유하게 식별할 수 있는 문자열 또는 숫자key로 지정해야함

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

Key는 각 컴포넌트가 어떤 배열 항목에 해당하는지 React에 알려주어 나중에 맵핑
배열 항목이 이동할 경우(index가 바뀌는 경우) 중요
key를 잘 선택하면 React가 정확히 무슨 일이 일어났는지 추론하고 DOM 트리에 올바르게 업데이트
즉석에서 key를 생성하는 대신 데이터 안에 key를 포함해야함

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>;
}

🚨 중요합니다!

map() 호출 내부의 JSX 엘리먼트에는 항상 key가 필요

🚨 각 리스트 항목에 대해 여러 DOM 노드 표시하기

여러 개의 DOM 노드를 렌더링해야 하는 경우 → <div> 또는 <Fragment> 를 사용하여 key 전달
Fragment는 DOM에서 사라지므로 <h1>, <p>, <h1>, <p> 등의 평평한 리스트 생성

import { Fragment } from 'react';

// ...

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

✅ key를 가져오는 곳

데이터 소스마다 다른 key 소스 제공

  • 데이터베이스의 데이터: : 데이터베이스에서 데이터를 가져오는 경우 고유한 데이터베이스 key 사용
  • 로컬에서 생성된 데이터: 데이터가 로컬에서 생성되고 유지되는 경우, 항목을 만들 때 id나 uuid 같은 패키지 사용

✅ key 규칙

  • key는 형제 간에 unique
    • 하지만 같은 key를 다른 배열의 JSX 노드에 동일한 key를 사용해도 OK
  • key는 변경되어서는 안됨
    • 그렇게 되면 key가 목적에 어긋나게 때문에 렌더링 중에 key 생성 ❌

✅ React에 key가 필요한 이유는 무엇인가요?

폴더의 파일 이름과 배열의 JSX key는 비슷한 용도로 사용
-> 형제 항목 간에 항목을 고유하게 식별
잘 선택된 key는 배열 내 위치보다 더 많은 정보를 제공
-> 위치가 변경되더라도 생명주기 내내 해당 항목을 key로 식별 가능

🚨 주의하세요!

배열에서 항목의 index를 key로 사용 유의 🚨
key를 전혀 지정하지 않으면 React는 인덱스를 사용하긴 함
But, 배열의 순서가 바뀌면 시간이 지남에 따라 항목을 렌더링하는 순서 변경
key={Math.random()} 과 같이 즉석에서 key 생성 ❌
→ 렌더링 간에 key가 일치하지 않아 모든 컴포넌트와 DOM 재생성
속도가 느려질 뿐만 아니라 리스트 항목 내부의 모든 사용자 입력 손실
컴포넌트가 key를 prop으로 받지 않음 → React 자체에서 힌트로만 사용

https://ko.react.dev/learn/rendering-lists

profile
단단한 프론트엔드 개발자가 되고 싶은

0개의 댓글