컴포넌트는 때때로 다른 조건에 따라 다른 것을 보여줄 필요가 있다. 리액트에서 if
문, &&
, ? :
연산자들과 같은 자바스크립트 문법을 사용하여 조건부로 JSX를 렌더링 하는 것이 가능하다.
배울 것
- 조건에 따라 다른 JSX를 리턴하는 방법
- 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>;
isPacked
이 true
일 때 이 코드는 다른 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 문을 사용하여 분기 논리를 만드는 방법에 주목하라. 리액트에서 제어 흐름은 자바스크립트에 의해 처리된다.
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에 컴포넌트를 조건부로 포함하거나 제외하는 경우가 더 많다.
이전 예시에서는 컴포넌트에서 반환할 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를 포함할 수 있다.
자바스크립트는 조건부 연산자 또는 '삼항 연산자'라는 조건부 표현식을 작성하기 위한 압축 구문이 있다.
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
을 렌더링 한다."
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>
);
}
이 스타일은 간단한 조건에서는 잘 작동하지만 적당히 사용해야 한다. 너무 많은 중첩 조건부 마크업으로 컴포넌트가 지저분해지는 경우, 자식 컴포넌트를 추출하여 항목을 정리하는 것이 좋다. 리액트에서 마크업은 코드의 일부이므로 변수 및 함수와 같은 도구를 사용하여 복잡한 식을 정리할 수 있다.
&&
)또 다른 일반적인 방법은 자바스크립트 논리 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>
위의 방법이 일반적인 코드를 쓰는 데에 방해가 되면 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>
);
}
자바스크립트에 익숙하지 않다면, 처음에는 이러한 다양한 스타일이 압도적으로 보일 수 있다. 하지만 그것들을 배우는 것은 단순히 리액트 컴포넌트가 아니라 자바스크립트 코드를 읽고 쓰는 데에 도움이 될 것이다. 먼저 원하는 방식을 하나 정하고 다른 항목의 작동 방식을 잊어버린 경우 이 참조를 다시 참조하라.
if
문을 사용하여 조건부로 JSX식을 반환할 수 있다.{cond ? <A /> : <B />}
은 "cond
이면 <A />
를 렌더링하고 그렇지 않으면 <B />
를 렌더링 한다" 를 뜻한다.{cond && <A />}
는 "cond
가 참이면 <A />
를 렌더링하고, 그렇지 않으면 아무것도 반환하지 않는다" 를 뜻한다.if
문을 선호한다면 그냥 사용해도 무관하다.