[React] Conditional Rendering

문지은·2023년 7월 15일
0

React

목록 보기
8/24
post-thumbnail

Conditional Rendering

  • Conditional Rendering
    • 어떠한 조건(true/false)에 따라서 렌더링이 달라지는 것

예시

  • 이미 회원인 사용자에게 보여줄 메시지를 출력할 UserGreeting 컴포넌트
function UserGreeting(props) {
    return <h1>다시 오셨군요!</h1>;
}
  • 아직 가입하지 않은 게스트 사용자에게 보여줄 메시지를 출력할 GuestGreeting 컴포넌트
function GuestGreeting(props) {
    return <h1>회원가입을 해주세요.</h1>;
}
  • 회원인지 아닌지에 따라 위 두 개의 컴포넌트를 선택적으로 보여주도록 조건부 렌더링을 사용하여 구현해보자.
    • isLoggedIn이라는 변수 값이 true 이면 UserGreeting 컴포넌트를, 그렇지 않으면 GuestGreeting 컴포넌트를 리턴하도록 하면 된다.
function Greeting(props) {
    const isLoggedIn = props.isLoggedIn;

    if (isLoggedIn) {
        return <UserGreeting/ >
    }
    return <GuestGreeting/ >
}

자바스크립트의 Truthy와 Falsy

  • 보통 프로그래밍 언어에서는 참, 거짓을 구분하기 위해 Boolean 형태의 자료형이 존재하고, 그 값은 true와 false 둘 중 하나가 된다.
  • 자바스크립트에서는 true는 아니지만 true로 여겨지는 값이 존재하는 데, 이것을 truthy라고 부른다.
  • 마찬가지로 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)
    • On (BigInt Zero)
    • '', "", `` (empty string)
    • null
    • undefined
    • NaN (not a number)

Element Variables

  • Element Variables (엘리먼트 변수)
    • 리액트 엘리먼트를 변수처럼 저장해서 사용하는 방법

예시

  • 사용자의 로그인 여부에 따라 선택적으로 보여줄 로그인 버튼과 로그아웃 버튼
function LoginButton(props) {
    return(
        <button onClick={props.onClick}>
            로그인
        </button>
    );
}

function LogoutButton(props) {
    return(
        <button onClick={props.onClick}>
            로그아웃
        </button>
    );
}
  • 두 개의 버튼을 로그인 여부에 따라 button이라는 변수에 컴포넌트를 대입하도록 엘리먼트 변수를 작성해보자.
function LoginControl(props) {
    const [isLoggendIn, setIsLoggendIn] = useState(false);

    const handleLoginClick = () => {
        setIsLoggendIn(true);
    }

    const handleLogoutClick = () => {
        setIsLoggendIn(false);
    }

    let button;
    if (isLoggendIn) {
        button = <LogoutButton onClick={handleLogoutClick} />;
    } else {
        button = <LoginButton onClick={handleLoginClick} />;
    }

    return (
        <div>
            <Greeting isLoggendIn={isLoggendIn} />
            {button}
        </div>
    );
}

Inline Conditions

  • 인라인 조건(Inline Conditions)
    • 조건문을 코드 안에 집어 넣는 것

인라인 If

  • if 문을 필요한 것에 직접 넣어서 사용하는 방법
  • AND 논리 연산자 && 사용
    • 양쪽에 나오는 조건문에 모두 true인 경우에만 전체 결과가 true
  • 단축 평가(Short-circuit evaluation)
    • AND 연산 시 첫번째 조건문이 true 이면 두 번째 조건문 평가
    • AND 연산 시 첫번째 조건문이 false이면 어차피 전체 결과가 false가 되므로 두 번째 조건문은 평가하지 않는다.
  • 즉, 단축 평가에 의해 조건문이 true이면 오른쪽에 나오는 엘리먼트가 결괏값이 되고, false 이면 false가 결괏값이 된다.
true && expression -> expression
fasle && expression -> false
  • 인라인 If는 && 연산자를 JSX 코드 안에 중괄호를 사용하여 직접 넣어서 사용한다.
  • unreadMessages.length > 0의 값에 따라 뒤에 나오는 <h2> 태그로 둘러싸인 부분이 렌더링이 되거나 안되게 하는 코드
function Mailbox(props) {
    const unreadMessages = props.unreadMessages;

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

주의사항 !

  • && 연산자를 사용할 때 조건문에 Falsy expression을 사용하면 뒤에 나오는 expression은 평가되지 않지만 Falsy expression의 결괏 값이 그대로 리턴된다.
  • 예를 들어, 아래 코드에서는 화면에 아무것도 나오지 않는 것이 아니라 count의 값인 0이 들어가서 <div>0</div>이 된다.
function Counter(props) {
    const count = 0;

    return (
        <div>
            {count && <h1>현재 카운트: {count}</h1>}
        </div>
    );
}

인라인 If-Else

  • 조건문의 값에 따라 다른 엘리먼트를 보여줄 때 사용
  • 삼항연산자 ? 사용
    • ? 앞에 나오는 조건문이 true일 경우 첫 번째 항목을 리턴하고, false일 경우 두번째 항목을 리턴
조건문 ? 참일 경우 : 거짓일 경우
  • 실제 리액트에서 사용하는 형태는 다음과 같다.
  • isLoggedIn의 값이 true인 경우 '로그인' 문자열을, false인 경우 '로그인 하지 않은' 문자열을 출력
function UserStatus(props) {
    return (
        <div>
            이 사용자는 현재 <b>{props.isLoggedin ? '로그인' : '로그인하지 않은'}</b> 상태입니다.
        </div>
    );
}
  • 아래 코드처럼 문자열이 아닌 엘리먼트를 넣어서 사용할 수도 있다.
    • isLoggedIn 이 true인 경우 LogoutButton을, false인 경우 LoginButton을 출력
function LoginControl(props) {
    const [isLoggendIn, setIsLoggendIn] = useState(false);

    const handleLoginClick = () => {
        setIsLoggendIn(true);
    }

    const handleLogoutClick = () => {
        setIsLoggendIn(false);
    }

    return (
        <div>
            <Greeting isLoggendIn={isLoggendIn} />
            {isLoggendIn
                ? <LogoutButton onClick={handleLogoutClick} />
                : <LoginButton onClick={handleLoginClick} />}
        </div>
    );
}

컴포넌트 렌더링 막기

  • 특정 컴포넌트를 렌더링하고 싶지 않을 때는 null을 리턴하면 됨
    • 리액트에서는 null을 리턴하면 렌더링되지 않기 때문

예시

  • props.warining 값이 true인 경우에만 경고 메시지를 출력하고 false인 경우에는 아무것도 출력하지 않는 코드
function WarningBanner(props) {
    if (!props.warning) {
        return null;
    }

    return (
        <div>경고!</div>
    );
}
  • 위에서 작성한 WarningBanner 컴포넌트를 실제로 사용해보자.
  • showWarning이라는 state의 값을 WarningBanner 컴포넌트의 props로 전달하여 showWarning의 값에 따라 경고문을 표시하거나 표시하지 않도록 작성
function MainPage(props) {
    const [showWarning, setShowWarning] = useState(false);

    const handleToggleClick = () => {
        setShowWarning(prevShowWarning => !prevShowWarning);
    }

    return (
        <div>
            <WarningBanner warning={showWarning} />
            <button onClick={handleToggleClick}>
                {showWarning ? '감추기' : '보이기'}
            </button>
        </div>
    )
}

실습 - 로그인 여부를 나타내는 툴바 만들기

Toolbar 컴포넌트 작성

  • isLoggedIn(사용자의 로그인 여부) 값을 props로 받아 조건부 렌더링을 사용하여 환영 메시지를 표시하거나 감추고 로그인/로그아웃 버튼을 보여줌
    • && 연산자와 ? 연산자 두 가지 방법을 이용하여 조건부 렌더링 구현
// src/chapter_09/Toolbar.jsx

import React from "react";

const styles = {
    wrapper: {
        padding: 16,
        display: "flex",
        flexDirection: "row",
        borderBottom: "1px solid grey",
    },
    greeting: {
        marginRight: 8,
    },
};

function Toolbar(props) {
    const { isLoggedIn, onClickLogin, onClickLogout } = props;

    return (
        <div style={styles.wrapper}>
            {isLoggedIn && <span style={styles.greeting}>환영합니다!</span>}

            {isLoggedIn ? (
                <button onClick={onClickLogout}>로그아웃</button>
            ) : (
                <button onClick={onClickLogin}>로그인</button>
            )}
        </div>
    );
}

export default Toolbar;

LandingPage 컴포넌트 작성

  • useState() 훅을 사용해서 사용자의 로그인 여부를 관리
    • 이 값을 Toolbar 컴포넌트에 전달하여 로그인 여부에 따라 툴바에 적절한 사용자 인터페이스가 표시되도록 함
// src/chapter_09/LandingPage.jsx

import React, { useState } from "react";
import Toolbar from "./Toolbar";

function LandingPage(props) {
    const [isLoggedIn, setIsLoggedIn] = useState(false);

    const onClickLogin = () => {
        setIsLoggedIn(true);
    };

    const onClickLogout = () => {
        setIsLoggedIn(false);
    };

    return (
        <div>
            <Toolbar
                isLoggedIn={isLoggedIn}
                onClickLogin={onClickLogin}
                onClickLogout={onClickLogout}
            />
            <div style={{ padding: 16 }}>소플과 함께하는 리액트 공부!</div>
        </div>
    );
}

export default LandingPage;

index.js 파일 수정

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import LandingPage from './chapter_09/LandingPage';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <LandingPage />
  </React.StrictMode>
);

reportWebVitals();

실행 결과

  • 초기 상태는 로그인이 되지 않은 상태이기 때문에 환영 메시지는 보이지 않으며 로그인 버튼이 표시됨

  • 로그인 버튼을 누르면 로그인 상태가 바뀌면서 환영메시지와 로그아웃 버튼이 나오는 것을 볼 수 있음

실습 전체 코드

References

profile
코드로 꿈을 펼치는 개발자의 이야기, 노력과 열정이 가득한 곳 🌈

0개의 댓글