조건부 렌더링
조건부 렌더링(conditional rendering)
React에서는 상황에 따라 동일한 컴포넌트이지만 서로 다른 내용을 화면에 표시해야 할 경우가 생길 수 있습니다. 이러한 경우 다음과 같은 방법들을 사용하여 조건부로 JSX 코드를 렌더링할 수 있습니다.
1. if / else 조건문
2. 삼항 연산자(? :)
3. 논리 AND 연산자(&&)
React에서 조건부 렌더링은 자바스크립트의 조건문 처리와 비슷하게 동작합니다. if 문이나 조건부 연산자와 같은 자바스크립트 연산자를 사용하여 현재 상태를 나타내는 엘리먼트를 생성하면, React는 현재 상태에 맞도록 UI를 업데이트할 것입니다.
if / else 조건문
다음 예제는 사용자의 로그인 상태에 따라 Login 버튼과 Logout 버튼의 렌더링 여부를 결정하는 예제입니다.
예제(LoginPanel.js)
const Button = ({ name, isLoggedIn }) => {
if (isLoggedIn) {
return null;
}
return <button>{name}</button>;
};
const LoginPanel = () => {
return (
<>
<Button isLoggedIn={false} name="Login" />
<Button isLoggedIn={true} name="Logout" />
</>
);
};
export default LoginPanel;
위의 예제에서는 사용자의 로그인 상태를 isLoggedIn prop으로 Button 컴포넌트에 전달하고 있습니다. 만약 사용자가 로그인된 상태라면 true를 전달하고, 로그인되지 않은 상태라면 false를 전달하여 if 문을 통해 각 버튼의 렌더링 유무를 결정하고 있습니다.
여러분이 직접 isLoggedIn prop의 값을 true와 false로 변경해보면서 화면에 렌더링되는 결과를 확인해 봅시다.
또한, null 값을 반환함으로써 아무것도 렌더링하지 않을 수 있습니다. 하지만 실제로 컴포넌트에서 null을 반환하도록 구현하는 것은 좋은 습관이 아니며, 그보다는 부모 컴포넌트의 JSX에서 조건부로 해당 컴포넌트를 포함하거나 제외하는 것이 좋습니다.
삼항 연산자(? :)
삼항 연산자(ternary operator)는 유일하게 피연산자를 세 개나 가지는 조건 연산자로, 다음과 같은 문법을 통해 사용할 수 있습니다.
삼항 연산자 문법
condition ? exprIfTrue : exprIfFalse
물음표(?) 앞의 표현식의 결과에 따라 결괏값이 true이면 반환값1을 반환하고, 결괏값이 false이면 반환값2를 반환합니다.
따라서 앞서 살펴본 예제의 코드를 삼항 연산자를 사용하면 다음과 같이 표현할 수 있습니다.
예제(LoginPanel.js)
const Button = ({ name, isLoggedIn }) => {
return isLoggedIn ? null : <button>{name}</button>;
};
//...
논리 AND 연산자(&&)
또 다른 방법으로 자바스크립트의 논리 AND 연산자(&&)를 사용하여 조건부 렌더링을 표현할 수도 있습니다.
논리 AND 연산자는 주로 React 컴포넌트 내부에서 조건이 true일 때는 일부 JSX를 렌더링하지만 false일 경우에는 아무것도 렌더링하지 않을 때 자주 사용됩니다.
예제(App.js)
const Button = ({ name, isLoggedIn }) => {
return !isLoggedIn && <button>{name}</button>;
};
앞서 살펴본 예제에서는 isLoggedIn이 false일 경우에 로그인 버튼을 렌더링해야 하므로, isLoggedIn 앞에 논리 NOT 연산자(!)를 추가하여 true와 false 값이 서로 바뀌도록 구현하였습니다.
조건부 렌더링 예제
마지막으로 조건부 렌더링을 활용한 아주 간단한 로그인 예제를 구현해 보도록 하겠습니다.
다음 예제는 state와 props를 활용하여 isLoggedIn 값이 false일 경우에는 화면에 Login 버튼과 로그인 안내 텍스트가 렌더링되고, true일 경우에는 Logout 버튼과 회원 환영 텍스트가 렌더링되도록 구현한 예제입니다.
예제(LoginPanel.js)
import { useState } from "react";
const Greeting = (props) => {
if (props.isLoggedIn) {
return (
<p>
안녕하세요 <u>홍길동님</u>
</p>
);
}
return <p>로그인 후 이용하세요.</p>;
};
const Button = ({ name, onClick }) => {
return <button onClick={onClick}>{name}</button>;
};
const LoginPanel = () => {
const [isLoggedIn, setState] = useState(false);
const handleLoginClick = () => {
setState(true);
};
const handleLogoutClick = () => {
setState(false);
};
let button;
if (isLoggedIn) {
button = <Button name="Logout" onClick={handleLogoutClick} />;
} else {
button = <Button name="Login" onClick={handleLoginClick} />;
}
return (
<>
{button}
<Greeting isLoggedIn={isLoggedIn} />
</>
);
};
export default LoginPanel;
위의 코드에서는 isLoggedIn 값에 따라 변수 button에 저장되는 컴포넌트의 내용이 달라지게 되며, Greeting 컴포넌트의 반환값도 달라지게 됩니다. 위의 예제처럼 조건문과 변수를 사용하여 부모 컴포넌트 단계에서 조건부로 자식 컴포넌트를 렌더링하는 것이 보다 일반적인 방법입니다.