본문 바로가기
공부기록/리액트

[REACT] 렌더링 - 공식 문서랑 같이 공부하기 시리즈6

by 책읽는 개발자 ami 2023. 11. 15.
728x90
반응형

조건부 렌더링

컴포넌트 내부에 조건문으로 JSX를 동적으로 표현할 수 있다. (if문, 삼항 연산자, 논리 연산자 &&)

if문

function Item({ name, isPacked }) {
  if (isPacked) {
    return <li className="item">{name} ✔</li>;
  }
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

특정 조건일 땐 아무것도 반환하고 싶지 않다면 null 을 사용하면 된다.

if (isPacked) {
  return null;
}
return <li className="item">{name}</li>;
 

하지만 이 방법은 일반적이진 않는다. null 대신 조건부에서 제외시키는 방법으로 사용하는 것이 더욱 일반적이다. 

삼항 연산자

if (isPacked) {
  return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;

위 코드는 딱 보기에도 중복된다. 문제가 되는 건 아니지만 보통 개발자들은 중복을 싫어하기 때문에 이런 경우 삼항 연산자를 사용하여 아래와 같이 사용한다.

return (
  <li className="item">
    {isPacked ? name + ' ✔' : name}
  </li>
);

논리 연산자 && (AND)

리액트 컴포넌트에서 어떤 조건이 true 일 때 JSX를 렌더링하고, false 일 땐 아무 동작도 안 하기 위해서 && 연산자를 사용한다. 

return (
  <li className="item">
    {name} {isPacked && '✔'}
  </li>
);

Javascript에서 && 연산자는 왼 쪽이 true 일 경우 오른 쪽을 반환한다. 만약 왼 쪽이 false일 경우 표현식 전체가 false가 된다. 이렇게 되면, 리액트는 아무것도 렌더링 하지 않는다.

** 왼 쪽에 숫자 0을 넣으면 안 된다. 0이면 false로 인식하는 게 아니라 리액트는 말그래도 0으로 인식하기 때문에 0을 렌더링하게 된다. 무조건 boolean 형식으로 만들어주어야 한다.

변수에 조건부로 JSX 할당하기

제일 많이 사용하는 방법이다.

function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = name + " ✔";
  }
  return (
    <li className="item">
      {itemContent}
    </li>
  );
}

코드로만 따지면 가장 길지만 가장 유연해서 제일 많이 사용한다.

목록 렌더링

배열에서 데이터 렌더링하기

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

위 HTML 소스를 보면 컴포넌트는 동일하고 안의 data만 바뀐다. 해당 데이터를 자바스크립트의 객체와 배열에 저장하고 map을 사용하여 컴포넌트 목록을 렌더링할 수 있다.

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

위 코드는 문제 없이 렌더링은 되지만 콘솔 창에 warning이 뜬다. key 가 없기 때문이다. 이 문제는 아래서 다시 다뤄보도록 한다. (Warning: Each child in a list should have a unique “key” prop.)

Key

각 항목(item)에는 key가 있어야 하는데, key는 배열 내에서 유니크한 문자열 또는 숫자여야 한다. 

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

 

그렇다면 key는 보통 어디서 가지고 올까?

1. 데이터베이스의 데이터: 주로 ID를 사용한다.

2. 로컬에서 생성된 데이터: DB를 안 쓰는 앱같은 경우엔 incrementing counter, crypto.randomUUID(), uuid 패키지 등을 사용할 수 있다.

key 규칙

1. sibling 사이에서는 고유해야 한다. 즉 다른 배열에는 동일한 key를 사용해도 된다.

2. key는 변경되지 않아야 한다. 

리액트에서 key가 필요한 이유

쉽게 생각하면 폴더 내 파일 이름을 key라고 생각하면 된다. key가 없으면 리액트는 index를 key 삼아 사용하지만 이는 배열이 변경됨에 따라 계속 바뀐다. 그래서 가끔 알 수 없는 버그를 일으킬지도..? (공식 문서 왈)

그리고 key를 즉석에서 생성할 경우 (예를 들어 key = { Math.random() }) 랜더링 할 때마다 key가 바뀌고, 그 말은 즉, 매번 모든 컴포넌트와 DOM이 다시 생성된다는 말이다. 이는 속도를 느려지게 하고 사용자가 입력한 데이터가 손실될 수도 있다. 

또한 key는 prop에 포함되지 않는다. 따라서 key가 필요할 경우 <Profile key={id} userId={id} />와 같이 따로 지정해주어야 한다.

728x90
반응형