본문 바로가기

개발공부/REACT

Conditional Rendering의 정의, JavaScript의 Truthy와 Falsy, Element Variables의 개념, Inline Conditions [처음 만난 리액트 #26]

9강. Conditional Rendering


Conditional Rendering이란?

- Condition은 영단어로 조건이라는 의미입니다.

- Conditional Rendering은 조건에 따른 렌더링이라는 뜻  조건부 렌더링

: 어떠한 조건에 따라서 렌더링이 달라지는 것 

 

* 여기서 조건이란? 프로그래밍에서 사용하는 조건문을 말합니다.

조건문의 결과는 true아니면 false가 나오는데, 이 결과에 따라서 렌더링이 달라지는 것을 조건부 렌더링이라고 합니다.

ex) True이면 버튼을 보여주고, False이면 버튼을 가릴 때

 

 

function UserGreeting(props) {
    return <h1>다시 오셨군요!</h1>;
}

function GuestGreeting(props) {
    return <h1>회원가입을 해주세요.</h1>;
}

 

UserGreetingGuestGreeting이라는 두 개의 함수 컴포넌트

  • UserGreeting 컴포넌트는 이미 회원인 사용자에게 보여줄 메세지를 출력하는 컴포넌트입니다.
  • GuestGreeting 컴포넌트는 아직 가입하지 않은 게스트 사용자에게 보여줄 메세지를 출력하는 컴포넌트입니다.

→ 회원인지 아닌지에 따라 이 두 개의 컴포넌트를 선택적으로 보여주어야 합니다. : 조건부 렌더링을 사용해서 구현할 수 있습니다.

 

 

function Greeting(props) {
    const isLoggedIn = props.isLoggedIn;
    
    if (isLoggedIn) {
        return <UserGreeting />;
    }
    return <GuestGreeting />;
}

 

▲ Greeting 컴포넌트

: isLoggedIn이라는 변수 값이 True에 해당되는 값이면 UserGreeting 컴포넌트를 리턴하고, False에 해당되는 값이면 GuestGreeting 컴포넌트를 리턴하는 컴포넌트입니다.

(조건부 렌더링)

 


JavaScript의 Truthy와 Falsy

보통의 프로그래밍 언어에서는 참과 거짓을 구분하기 위해 Boolean 자료형이 존재하고,

그 값은 참(true)과 거짓(false) 둘 중 한가지가 됩니다.

 

Boolean과 자료형이 다른 값을 비교하게 되면 오류가 발생하게 됩니다.

 

 

Truthy

: 자바스크립트에서는 true는 아니지만 true로 여겨지는 값인 truthy가 존재합니다.

Falsy

: 자바스크립트에서는 false는 아니지만 false로 여겨지는 값인 falsy가 존재합니다.

 

// truthy
true
{} (empty object)
[] (empty array)
42 (number, not zero)
"0", "false" (string, not empty)

// falsy
false 
0, -0 (zero, minus zero)
0n (BigInt zero)
'', "", `` (empty string)
null
undefined
NaN (not a number)

 


Element Variables

조건부 렌더링을 사용하다 보면 렌더링해야 할 컴포넌트를 변수처럼 다루고싶을 때 Element Variables(엘리먼트 변수)를 사용합니다.

Element Variables : 리액트의 element를 변수처럼 다루는 방법

 

function LoginButton(props) {
    return ( 
        <button onClick={props.onClick}>
            로그인
        </button>
    );
}

function LogoutButton(props) {
    return (
        <button onClick={props.onClick}>
            로그아웃
        </button>
    );
}

 

▲ LoginButton과 LogoutButton 두 개의 컴포넌트

각 컴포넌트는 로그인 버튼과 로그아웃 버튼을 나타냅니다.

 

 

function LoginControl(props) {
    const [isLoggedIn, setIsLoggedIn] = useState(false);
    
    const handleLoginClick = () => {
        setIsLoggedIn(true);
    }
    
    const handleLogoutClick = () => {
        setIsLoggedIn(false);
    }
    
    let button;
    if (isLoggedIn) {
        button = <LogoutButton onClick={handleLogoutClick} />;
    } else {
        button = <LoginButton onClick={handleLoginClick} />;
    }
    
    return (
        <div>
            <Greeting isLoggedIn={isLoggedIn} />
            {button}
        </div>
    )
}

 

▲ LoginControl 컴포넌트

  • LoginControl 컴포넌트는 사용자의 로그인 여부에 따라 LoginButton과 LogoutButton 두 개의 컴포넌트를 선택적으로 보여줍니다.
  • 중간 조건문을 보면, isLoggedIn 값에 따라서 변수에 컴포넌트를 대입하는 것을 볼 수 있습니다. 
  • 컴포넌트가 대입된 변수 button을 리턴에 넣어 실제로 컴포넌트가 렌더링 되도록 만들고 있습니다. : 실제로는 컴포넌트가 아니라, 컴포넌트로부터 생성된 react element

: 엘리먼트를 변수처럼 저장해서 사용하는 방법인 Element Variables을 사용

 


Inlilne Conditions (인라인 조건문)

위의 LoginControl 컴포넌트 코드처럼 별도로 변수를 선언해서 조건부 렌더링을 할 수도 있지만, 인라인 조건문을 사용하면 조금 더 코드를 간결하게 작성할 수 있습니다.

 

- In + lilne : 라인의 안

코드를 별도로 분리된 곳에 작성하지 않고, 해당 코드가 필요한 곳 안에 직접 집어넣는다는 의미

Inlilne Conditions : 조건문을 코드 안에 집어넣는 것


Inline If

  • if 문을 필요한 곳에 직접 집어넣어 사용하는 방법
  • 실제로 if 문을 넣는 것은 아니고, if 문과 동일한 효과를 내기 위해 &&라는 논리연산자를 사용합니다.
  • && 연산자를 jsx 코드 안에서 중괄호를 사용하여 직접 집어넣는 방법입니다.

 

&& (logical and 연산)

양쪽의 조건문이 모두 true인 경우에만 전체 결과가 true가 됩니다.

 

첫 번째 조건문이 true이면, 두 번째 조건문을 평가하고

첫 번째 조건문이 false이면, 어차피 전체 결과는 false이므로 두 번째 조건문을 평가하지 않습니다

: 단축 평가 (short circuit evaluation)

- 결과가 정해져있는 논리연산에서 불필요한 연산을 하지 않도록 하기 위해 사용하는 방법

 

첫 번째 조건문의 값에 따른 && 연산자의 결과값

 

조건문이 true이면 뒤에 나오는 expression이 평가되고, 조건문이 false이면 단축 평가에 의해서 뒤에 나오는 expression은 전혀 평가되지 않습니다.

→ 리액트에서는 조건문이 true이면 오른쪽에 나오는 엘리먼트가 결과값이 되고, 조건문이 false이면 false가 결과값이 됩니다.

 

function Mailbox(props) {
    const unreadMessages = props.unreadMessages;
    
    return (
        <div>
            <h1>안녕하세요!</h1>
            {unreadMessages.length > 0 &&
                <h2>
                    현재 {unreadMessages.length}개의 읽지 않은 메시지가 있습니다.
                </h2>
            }
        </div>
    );
}

 

unreadMessages.length가 0보다 큰지 평가하는 조건문의 결과값에 따라서,

뒤에 나오는 h2 태그로 둘러쌓이는 부분이 렌더링이 되거나 안되거나 하게 됨

  • unreadMessages.length가 0보다 크다면 뒤에 나오는 h2 태그 부분이 렌더링됩니다.
  • unreadMessages.length가 0보다 작다면 아무것도 렌더링 되지 않습니다.

 

&& 연산자를 사용할 때 조건문에 false expression을 사용하면 뒤에 나오는 expression은 평가되지 않지만, false expression의 결과값이 그대로 리턴된다는 것을 주의!

function Counter(props) {
    const count = 0;
    
    return (
        <div>
            {count && <h1>현재 카운트: {count}</h1>}
        </div>
    );
}

 

이 코드의 결과는 화면에 아무것도 안 나오는 것이 아니라 count의 값인 0이 들어가서 <div> 0 </div> 가 됩니다.

 


Inline If-Else

  • If-Else 문을 필요한 곳에 직접 집어넣어 사용하는 방법
  • Inline If는 보여주거나, 안 보여주거나 두 가지만 있었지만 Inline If-Else는 조건문의 값에 따라서 다른 element를 보여줄 때 사용합니다.
  • 삼항 연산자인 ? 연산자를 사용합니다.

 

? 연산자 (삼항 연산자)

 

 

조건문이 true이면 첫 번째 항목을 리턴하고, false이면 두 번째 항목을 리턴

총 세 개의 항이 있기 때문에 삼항연산자라고 부릅니다.

 

function UserStatus(props) {
    return (
        <div>
            이 사용자는 현재 <b>{props.isLoggedIn ? '로그인' : '로그인하지 않은'}</b> 상태입니다.
        </div>
    )
}

 

Inline If-Else를 사용한 부분을 보면,

props.isLoggedIn의 값이 true인 경우에는 '로그인'이라는 문자열을 출력하고,  false인 경우에는 '로그인하지 않은'라는 문자열을 출력하게 됩니다.

 

function LoginControl(props) {
    const [isLoggedIn, setIsLoggedIn] = useState(false);
    
    const handleLoginClick = () => {
        setIsLoggedIn(true);
    }
    
    const handleLogoutClick = () => {
        setIsLoggedIn(false);
    }
    
    return (
        <div>
            <Greeting isLoggedIn={isLoggedIn} />
            {isLoggedIn
                ? <LogoutButton onClick={handleLogoutClick} />
                : <LoginButton onClick={handleLoginClick} />
            }
        </div>
    )
}

 

▲ 문자열이 아닌 엘리먼트를 넣어서 사용한 경우 

isLoggedIn의 값이 true인 경우에 LogoutButton을 출력하고 false인 경우에는 LoginButton을 출력하게 됩니다.

 


Component 렌더링 막기

컴포넌트를 렌더링하고 싶지 않을 때?

null을 리턴하면 렌더링되지 않습니다.

 

function WarningBanner(props) {
    if (!props.warning) {
        return null;
    }
    
    return (
        <div>경고!</div>
    );
}

 

▲ WarningBanner 컴포넌트

: props.warning의 값이 false인 경우에는 null을 리턴합니다.

props.warning의 값이 true인 경우에만 경고메시지를 출력하고, false인 경우에는 아무것도 출력하지 않는 컴포넌트  

 

 

function MainPage(props) {
    const [showWarning, setShowWarning] = useState(false);
    
    const handleToggleClick = () => {
        setShowWarning(prevShowWarning => !prevShowWarning);
    }
    
    return (
        <div>
            <WarningBanner warning={showWarning} />
            <button onClick={handleToggleClick}>
                {showWarning ? '감추기' : '보이기'}
            </button>
        </div>
    )
}

 

 WarningBanner 컴포넌트를 실제로 사용하는 코드

MainPage 컴포넌트는 showWarning이라는 state의 값을 WarningBanner의 props로 전달하여 showWarning의 값에 따라 경고문을 표시하거나 표시하지 않게 됩니다.