Describing the UI - Conditional Rendering

hyocho·2023년 5월 24일
0

React

목록 보기
17/24
post-thumbnail
post-custom-banner

출처 : https://react.dev/learn/conditional-rendering

컴포넌트는 때때로 다른 조건에 따라 다른 것을 보여줄 필요가 있다. 리액트에서 if문, &&, ? : 연산자들과 같은 자바스크립트 문법을 사용하여 조건부로 JSX를 렌더링 하는 것이 가능하다.

배울 것

  • 조건에 따라 다른 JSX를 리턴하는 방법
  • JSX의 일부를 조건부로 포함하거나 제외하는 방법
  • 리액트 코드 베이스에서 마주할 수 있는 일반적인 조건부 구문

Conditionally returning JSX

여러 Item을 렌더링 하는 PackingList 컴포넌트가 있다고 가정해보자. 이러한 항목은 포장되었다 혹은 되지 않았다로 표시될 수 있다.

function Item({ name, isPacked }) {
  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>
  );
}

일부 Item 컴포넌트는 isPacked prop이 false대신 true라고 설정되어 있다. isPacked={true} 일 때 체크 마크(✔)를 표시하고 싶을 수 있다.

if/else 구문을 아래와 같이 사용할 수 있다.

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

isPackedtrue일 때 이 코드는 다른 JSX 트리를 반환한다. 이 변화로 어떤 항목은 체크마크를 얻게 될 것이다.

//@App.js
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>
  );
}

두 가지의 경우를 수정하여 결과가 어떻게 변하는지 확인해보라.

자바스크립트의 if 및 return 문을 사용하여 분기 논리를 만드는 방법에 주목하라. 리액트에서 제어 흐름은 자바스크립트에 의해 처리된다.

Conditionally returning nothing with null

어떤 조건에서는 어떤 것도 렌더하고 싶지 않을 수 있다. 예를 들어, 포장된 항목을 전혀 표시하지 않겠다고 가정할 수 있다. 컴포넌트는 반드시 어떤 것을 반환해야 한다. 이 경우 null을 반환할 수 있다.

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

isPacked가 true이면 컴포넌트는 null을 반환할 것이다. 그렇지 않으면 렌더하기 위해 JSX를 반환할 것이다.

//@App.js
function Item({ name, isPacked }) {
  if (isPacked) {
    return null;
  }
  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을 반환하는 것은 일반적이지는 않다. 부모 컴포넌트의 JSX에 컴포넌트를 조건부로 포함하거나 제외하는 경우가 더 많다.

Conditionally including JSX

이전 예시에서는 컴포넌트에서 반환할 JSX트리(있는 경우)를 제어했다. 렌더링 출력에서 일부 중복이 이미 발견되었을 수 있다.

<li className="item">{name}</li>

은 아래와 매우 유사하다

<li className="item">{name}</li>

두 분기 모두 <li className="item">...</li>을 반환한다.

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

이 복제는 유해한 것은 아니지만, 코드 유지보수에 어려움을 줄 수 있다. className을 변경하려면 어떻게 해야하는가? 코드의 두 곳에서 수행해야 한다. 이러한 상황에서는 코드를 더 DRY하게 만들기 위해 조건부로 약간의 JSX를 포함할 수 있다.

Conditional (ternary) operator (? :)

자바스크립트는 조건부 연산자 또는 '삼항 연산자'라는 조건부 표현식을 작성하기 위한 압축 구문이 있다.

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

이것 대신

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

이렇게 쓸 수 있다.
"만약 isPacked가 참이면, (?) name + ' ✔'을 렌더링 할 것이고, 아니면 (:) name을 렌더링 한다."

DEEP DIVE

Are these two examples fully equivalent?
객체 지향 프로그래밍 배경 지식을 가지고 있다면, 위의 두 예시 중 하나가 <li>의 두 개의 다른 '인스턴스'를 만들 수 있기 때문에 두 예시는 다르다고 생각할 수 있다. 그러나 JSX요소는 내부 상태를 유지하지 않으며 실제 DOM노드가 아니기 때문에 인스턴스가 아니다. 그것들은 청사진과 같은 가벼운 묘사이다. 그래서 이 두가지 예는 사실 완전히 같다. 상태 보존 및 재설정은 이 작업 방식에 대해 자세히 설명한다.

이제 완료된 항목의 텍스트를 <del>과 같은 다른 HTML태그로 포장하여 제거하려고 한다. 더 많은 줄과 괄호를 추가하여 각 경우에 더 많은 JSX를 더 쉽게 중첩할 수 있다.

//@App.js
function Item({ name, isPacked }) {
  return (
    <li className="item">
      {isPacked ? (
        <del>
          {name + ' ✔'}
        </del>
      ) : (
        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>
  );
}

이 스타일은 간단한 조건에서는 잘 작동하지만 적당히 사용해야 한다. 너무 많은 중첩 조건부 마크업으로 컴포넌트가 지저분해지는 경우, 자식 컴포넌트를 추출하여 항목을 정리하는 것이 좋다. 리액트에서 마크업은 코드의 일부이므로 변수 및 함수와 같은 도구를 사용하여 복잡한 식을 정리할 수 있다.

Logical AND operator (&&)

또 다른 일반적인 방법은 자바스크립트 논리 AND(&&) 연산자이다. 리액트 컴포넌트 내에서 조건이 참일 때 일부 JSX를 렌더링하거나 다른 어떤 것도 렌더링하지 않을 때 자주 나타난다. &&을 사용하면 isPacked가 참일 경우에만 조건부로 체크 표시를 렌더링할 수 있다.

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

"isPacked가 참일 때, (&&)는 체크 마크를 렌더링 할 것이고 아니라면 아무것도 렌더링하지 않을 것이다.

//@App.js
function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✔'}
    </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또는 undefined와 마찬가지로 거짓을 트리의 '구멍'이라고 간주하고 대신 아무것도 렌더링하지 않는다.

Don’t put numbers on the left side of &&.
조건을 테스트하기 위해 자바스크립트는 자동으로 왼쪽을 불린형으로 변화시킨다. 그러나 왼쪽이 0이면, 전체 식이 해당 값 0을 얻으며 리액트는 아무것도 렌더링 하지 않는 대신 0을 렌더링한다.
예를 들어 일반적인 실수는 messageCount && <p>New messages</p>와 같이 쓰는 것이다. messageCount가 0이면 아무것도 렌더링하지 않는다고 가정하기 쉽지만 실제로는 0 자체를 렌더링한다.
수정하려면 왼쪽을 불린으로 만들어야 한다 : messageCount > 0 && <p>New messages</p>

Conditionally assigning JSX to a variable

위의 방법이 일반적인 코드를 쓰는 데에 방해가 되면 if문과 변수를 사용해보라. let으로 정의된 변수를 재할당할 수 있어 표시할 기본 콘텐츠로 시작할 수 있다.

let itemContent = name;

isPacked가 참이면 itemContent을 재할당하는 JSX구문은 if문을 이용할 수 있다.

if (isPacked) {
  itemContent = name + " ✔";
}

중괄호로 자바스크립트로 통하는 창 이 열린다. 반환된 JSX트리에 중괄호가 있는 변수를 포함하고 이전에 계산된 식을 JSX내부에 중첩한다.

<li className="item">
  {itemContent}
</li>

이 스타일은 가장 장황하지만 가장 유연하다. 다음과 같이 작동한다.

//@App.js
function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = name + " ✔";
  }
  return (
    <li className="item">
      {itemContent}
    </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>
  );
}

이전처럼, 이것은 텍스트뿐 아니라 임의의 JSX에도 적용된다.

//@App.js
function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = (
      <del>
        {name + " ✔"}
      </del>
    );
  }
  return (
    <li className="item">
      {itemContent}
    </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>
  );
}

자바스크립트에 익숙하지 않다면, 처음에는 이러한 다양한 스타일이 압도적으로 보일 수 있다. 하지만 그것들을 배우는 것은 단순히 리액트 컴포넌트가 아니라 자바스크립트 코드를 읽고 쓰는 데에 도움이 될 것이다. 먼저 원하는 방식을 하나 정하고 다른 항목의 작동 방식을 잊어버린 경우 이 참조를 다시 참조하라.

RECAP

  • 리액트에서 자바스크립트를 사용하여 분기를 제어한다.
  • if문을 사용하여 조건부로 JSX식을 반환할 수 있다.
  • 일부 JSX를 조건부로 변수에 저정한 다음 중괄호를 사용하여 다른 JSX내부에 포함할 수 있다.
  • JSX에서 {cond ? <A /> : <B />}은 "cond이면 <A />를 렌더링하고 그렇지 않으면 <B />를 렌더링 한다" 를 뜻한다.
  • JSX에서 {cond && <A />}는 "cond가 참이면 <A />를 렌더링하고, 그렇지 않으면 아무것도 반환하지 않는다" 를 뜻한다.
  • shortcut(위의 방법)은 일반적이지만, 일반적인 if문을 선호한다면 그냥 사용해도 무관하다.
profile
기록하는 습관을 기르고 있습니다.
post-custom-banner

0개의 댓글