조건부 렌더링이란, 특정 조건에 따라 다른 결과물을 렌더링하는 것을 의미한다.
React에서 원하는 동작을 수행하는 캡슐화된 별개의 컴포넌트를 생성할 수 있다. 또한, state에 의존하여 그 중 일부만 렌더링시키는 것도 가능하다.
크게 3가지 방법으로 나누어 소개할 수 있다.
1) if-else 조건문
2) 논리연산자 &&
3) 조건부 연산자
사용자의 로그인 여부에 따라 <UserGreeting/>
또는 <GuestGreeting/>
컴포넌트를 표시하는 예시입니다.
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) { //isLoggedIn==true이면
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
// Try changing to isLoggedIn={true}:
<Greeting isLoggedIn={false} />,
document.getElementById('root')
);
if-else 패턴은 컴포넌트가 조건에 따라 렌더링할 내용 전체가 결정되는게 특징이다. 이 패턴은 컴포넌트의 일부분만 선택적으로 렌더링하기에 적합하지 않다.
예를 들어 아래와 같이 if-else를 적용하면 제대로 작동하지 않는다.
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
return (
<React.Fragment>
{
// 'Unexpected token' error 발생
if (isLoggedIn) {
return <UserGreeting />;
}
else {
return <GeustGreeting />;
}
}
</React.Fragment>
);
}
if-else 패턴을 사용하면서 일부분만 렌더링하려면 즉시 실행 함수 (IIFE) 를 사용해야 가능하다.
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
return (
<React.Fragment>
{
// 즉시 실행 함수 IIFE
(() => {
if (isLoggedIn) {
return <UserGreeting />;
}
else {
return <GeustGreeting />;
}
}
)();
}
</React.Fragment>
);
}
즉시 실행 함수를 사용한 if-else 패턴은 가독성이 떨어지는 문제가 있다. 또한 if-else 패턴으로 렌더링 대상 전체가 변경된다면, 새로운 컴포넌트를 작성하는게 더 적합하기 때문에 if else 패턴은 효과적으로 활용하기 어려운 패턴이다.
원래 논리연산자 &&는 "두 피연산자가 true이면 결론적으로 true를 반환한다" 라고만 알고있었다.
그런데 자바스크립트에서는 true && expression
은 항상 expression으로 평가되고 false && expression
은 항상 false로 평가되기 때문에 조건부 렌더링할때 유용하게 사용할 수 있다.
또한 중괄호 { } 로 감싸면 JSX에 어떤 표현식이던 넣을 수 있었습니다. 자바스크립트의 논리연산자 &&도 포함됩니다.
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
}
const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById('root')
);
위의 코드는 unreadMessages.length > 0
일때 <h2>
태그의 내용을 나타내는 예시입니다.
자바스크립트의 조건부 연산자인 condition ? true : false
를 사용하여 조건부 렌더링을 구현할 수 있다.
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
The user is <p>{isLoggedIn ? 'currently' : 'not'}</p> logged in.
</div>
);
}
컴포넌트가 다른 컴포넌트에 의해 렌더링 되었더라도 이를 숨길 수가 있다. 이때는 렌더 출력 대신 null
을 반환하면 됩니다.
아래 예시의 WarningBanner 컴포넌트는 warn
prop값을 받아서 해당값이 false라면 return null
을 해서 컴포넌트가 렌더링되지 않게 합니다.
function WarningBanner(props) {
if (!props.warn) { //warn==false이면
return null;
}
return (
<div className="warning"> Warning!</div>
);
컴포넌트의 props 값을 설정하게 될때 만약 props 이름만 작성하고 값을 따로 설정안한다면, true
로 설정한 것으로 간주됩니다.
import React from 'react';
import Hello from './Hello';
function App() {
return (
<div>
<Hello name="홍길동" color="red" isPerson />
<Hello color="pink"/>
</div>
);
}
export default App;
이와 같이 isPerson
만 props로 넘겨줬는데, 이는 isPerson={true}
와 동일한 의미라고 할 수 있습니다.
조건부 렌더링 및 setState 일괄처리 관련
https://hyeok999.github.io/2019/12/24/react-official-06/
조건부 렌더링 패턴 관련
https://ibocon.tistory.com/217