Skip to content
This page has been auto-translated and may contain errors.View in English

조건부 렌더링

로그인한 방문자는 대시보드를 보고, 로그인하지 않은 방문자는 로그인 폼을 보며, 요청이 실패하면 페이지 어딘가에 에러 메시지가 나타나야 합니다. isLoggedIn 같은 불린 값은 보통 state에 저장되며, 현재 값에 따라 어떤 UI를 렌더링할지가 결정됩니다. JSX는 JavaScript이므로, 무엇을 렌더링할지 결정하는 것은 코드의 다른 모든 결정과 같은 방식으로 작동합니다. return 문 안에서 바로 값을 선택하는 표현식을 평가하면 됩니다.

삼항 연산자로 두 요소 중 선택하기

UI가 정확히 두 가지 중 하나가 될 수 있을 때, 삼항 연산자를 사용합니다:

jsx
return (
  <div>
    {isLoggedIn ? <Dashboard /> : <Login />}
    {hasError && <p>Something went wrong</p>}
  </div>
)

isLoggedIn ? <Dashboard /> : <Login />는 다른 삼항 연산자처럼 읽힙니다. isLoggedIn이 참이면 이 표현식은 <Dashboard />로 평가되고, 그렇지 않으면 <Login />으로 평가됩니다. 평가된 결과가 무엇이든 JSX의 그 자리에 렌더링됩니다. 중괄호는 JavaScript 표현식을 마크업 중간에 삽입할 수 있게 해주며, 삼항 연산자는 다른 표현식처럼 하나의 표현식입니다.

&& 연산자로 한 요소 표시하거나 숨기기

두 번째 줄은 다른 형태의 결정을 다룹니다. 무언가를 표시하거나 아무것도 표시하지 않습니다. hasError && <p>Something went wrong</p>는 JavaScript의 다른 곳에서처럼 && 연산자를 사용합니다. hasErrorfalse이면, &&는 **단락 평가**되어 오른쪽의 JSX에 도달하지 않고 전체 표현식이 false로 평가됩니다. hasErrortrue이면, 표현식은 <p> 요소로 평가됩니다.

이것이 올바르게 렌더링되는 이유는 React가 결과에 대해 무엇을 하는지에 달려 있습니다. React는 false, null, undefined에 대해서는 아무것도 렌더링하지 않습니다. 따라서 hasErrorfalse일 때, 페이지에 아무것도 나타나지 않습니다.

거짓 값의 함정

&&truefalse만 생성하지 않습니다. &&를 사용하는 다른 JavaScript 표현식처럼, 이것은 도달한 쪽의 값으로 평가되며, 그 값은 반드시 불린일 필요가 없습니다. 대부분의 경우 문제가 되지 않지만, 왼쪽이 숫자일 때 버그가 됩니다:

jsx
{count && <Badge />}
// count = 0 → 페이지에 "0"을 렌더링합니다

count0이면, 이 표현식은 0으로 평가됩니다. React는 false, null, undefined에 대해서는 렌더링하지 않지만, 0은 실제 렌더링 가능한 값이므로 React는 이것을 페이지에 표시합니다. 배지는 나타나지 않지만, 여분의 0이 아무것도 표시될 것으로 예상된 곳에 나타납니다.

해결책은 &&의 왼쪽이 항상 실제 불린이 되도록 하는 것입니다:

jsx
{count > 0 && <Badge />}
// count = 0 → 아무것도 렌더링하지 않습니다

count > 0은 항상 true 또는 false로 평가되므로, 표현식은 배지를 렌더링하거나 아무것도 렌더링하지 않으며, 0이 남겨지지 않습니다.

아무것도 렌더링하지 않기

때로 컴포넌트는 표시할 것이 없으며, 이를 나타내는 가장 명확한 방법은 조기에 반환하는 것입니다:

jsx
function Banner({ message }) {
  if (!message) {
    return null
  }

  return <p className="banner">{message}</p>
}

message가 비어 있을 때, 함수는 JSX의 나머지를 구성하기 전에 null을 반환합니다. 이렇게 하면 주요 return이 실제로 렌더링할 것이 있는 경우에 집중되며, 전체를 하나의 조건으로 감싸는 대신 명확하게 유지됩니다.

어떤 도구를 사용할지는 조건이 무엇 중에서 선택하는지에 달려 있습니다. 두 요소 중: 삼항 연산자를 사용합니다. 한 요소 또는 아무것도 아님: &&를 사용합니다. 렌더링할 것이 아예 없는 컴포넌트: 주요 return 앞에 if (!x) return null로 조기 반환하며, 전체 JSX 트리를 하나의 조건으로 감싸는 대신입니다. 이들을 섞어서 사용하거나, &&로 충분한 곳에 삼항 연산자를 사용하거나, 삼항 연산자 안에 조기 반환을 숨기는 것은 보통 더 직접적인 도구로 전환해야 한다는 신호입니다.

{count && <Badge />}에서의 거짓 값 함정은 0에만 국한되지 않습니다. NaN도 같은 방식으로 렌더링되므로, {total / count && <Badge />}count0일 때 페이지에 NaN을 출력할 수 있습니다. 빈 문자열 ""은 같은 버그의 더 조용한 버전입니다. {name && <Greeting name={name} />}name""일 때 눈에 띄는 것은 렌더링하지 않지만(빈 문자열은 페이지에서 보이지 않기 때문), 여전히 DOM에 남겨진 여분의 텍스트 노드입니다. 해결책은 0에 사용되는 것과 같습니다. 왼쪽을 count > 0 같은 비교나 Boolean(...) 호출로 명시적인 불린으로 강제하여, 원본 값이 예상하는 방식으로 거짓이 되기를 믿지 않습니다.

한 번에 하나 이상의 조건이 있을 때 조건을 읽기가 어려워집니다. 다른 삼항 연산자 안에 중첩된 삼항 연산자는 조건이 인라인 논리를 벗어났다는 첫 번째 신호입니다:

jsx
{status === 'loading' ? <Spinner /> : status === 'error' ? <ErrorMessage /> : <Content />}

이를 정리하기 위한 두 가지 옵션이 있습니다. 결정을 return 위의 변수로 꺼내서, JSX는 이미 결정된 결과만 포함하면 됩니다:

jsx
const view =
  status === 'loading' ? <Spinner /> :
  status === 'error' ? <ErrorMessage /> :
  <Content />

return <div>{view}</div>

또는 로직을 올바른 요소를 반환하는 작은 헬퍼 함수로 추출합니다. 이것은 두 개 이상 세 개 정도의 분기가 있을 때 더 잘 읽힙니다. 어느 쪽이든, 목표는 동일합니다. JSX 자체를 결정에서 자유롭게 유지하고 위에서 이미 결정된 값만 포함합니다.

컴포넌트에서 null을 반환하면 아무것도 렌더링되지 않습니다. 그것에 대해 DOM 노드도 생성되지 않으며, 빈 것도 아닙니다. 이것은 컴포넌트에 대한 정당한 반환 값이며, React는 null 반환을 빈 fragment와 같은 방식으로 처리합니다.

같은 자리에서 컴포넌트를 교체하기 시작할 때 알아둘 가치 있는 두 번째 것이 있습니다. React는 트리를 위치별로 순회하며 재조정하며, 각 위치에서 지금 그 자리에 있는 요소의 타입을 마지막 렌더링에 있던 타입과 비교합니다.

jsx
{isEditing ? <EditForm /> : <ViewForm />}

isEditing이 뒤집히면, EditFormViewForm은 같은 위치를 차지하는 다른 컴포넌트 타입이므로, React는 이전 것을 마운트 해제하고 새 것을 처음부터 마운트합니다. 예를 들어, 사용자가 입력하던 입력 값과 같이 EditForm이 보유하던 모든 state는 ViewForm이 그 자리를 차지하는 순간 사라집니다. 이는 같은 위치에서 다른 props로 같은 컴포넌트 타입을 렌더링하는 것과 다릅니다. 같은 위치에 같은 타입이면 React는 기존 인스턴스를 업데이트하고 그 state는 유지됩니다. 타입은 React가 "같은 것이 업데이트됨"을 볼지 "완전히 새로운 것"을 볼지를 결정합니다.

Juno무엇을 표시할지 결정하는 것은 일반적인 JavaScript입니다 삼항 연산자는 두 요소 중 선택하고, &&는 한 요소를 표시하거나 아무것도 표시하지 않으며, 컴포넌트에서 null을 반환하는 것은 "렌더링할 것이 없습니다"라고 말하는 방법입니다. {count && <Badge />}에서 count0이 될 수 있을 때 주의하세요. 0은 React가 실제로 출력할 값이기 때문입니다. 대신 {count > 0 && <Badge />}를 쓰면 왼쪽이 참 불린으로 유지됩니다.
Juno무엇을 표시할지 결정하는 것은 일반적인 JavaScript입니다 두 요소 중 선택할 때는 삼항 연산자를 사용하고, 한 요소와 아무것도 아님 중 선택할 때는 &&를 사용합니다. &&와 함께 기억할 함정은 이것이 도달한 쪽의 값으로 평가되므로, 0 같은 거짓 숫자가 사라지는 대신 자기 자신으로 렌더링된다는 것입니다. 왼쪽을 count > 0 같은 명시적인 불린으로 만들어서 이로부터 보호하고, 컴포넌트가 표시할 것이 없을 때 조기 return null을 사용합니다.
Juno무엇을 표시할지 결정하는 것은 일반적인 JavaScript입니다 여기 있는 모든 조건부 렌더링 트릭은 JSX 내에서 평가되는 일반적인 JavaScript이며, React 관련 부분은 false, null, undefined는 아무것도 렌더링하지 않고 0을 포함한 다른 모든 값은 자기 자신으로 렌더링한다는 것뿐입니다. 이것이 {count && <Badge />}를 함정으로 만들고 {count > 0 && <Badge />}를 해결책으로 만듭니다. 앞으로 나아갈 때 기억할 가치 있는 부분은 위치와 타입으로 재조정하는 것입니다. 같은 자리에 다른 컴포넌트 타입을 교체하면 state는 사라집니다. React가 이전 것을 업데이트하는 대신 새로운 요소를 보기 때문입니다.

다음: Forms. 여기서는 state를 사용하여 입력 필드를 처리합니다.