도움말 - 글감 수집하기 (인용)

도움말 - 부분 리뷰 작성하기

리액트(React) 이해 기초 2 - Conditional Rendering

리액트로 컴포넌트를 만들다 보면, 빈번하게 사용 되는 패턴 중에 하나는 조건에 따라 다른 컴포넌트를 렌더링 하는 것이다. 예를 들어, 데이터가 로딩 중 일때, 데이터가 없을 때 등등 다양한 상황에서 조건식에 따라 다른 컴포넌트를 렌더링 해야 할 때가 있다. 기본적인 자바스크립트에서 제공하는 조건문(if/else, switch/case 등등)을 사용 하여 렌더링 하는 것 뿐만 아니라 IIFE, HOC, 객체(object) 등을 사용 하여 조건에 맞는 컴포넌트를 렌더링을 할 수도 있다. 이같은 다양한 방법에 대해 알아보자.

자바스크립트 조건문과 연산자를 사용한 방법

if / else

가장 기본적인 방법이다. 컴포넌트 prop 값에 따라 리턴하는 리액트 컴포넌트를 분기 처리한다.

const ConditionalComponent = ({ loading, data }) => {
if (loading) {
return <LoadingComponent />
}
return <h1>{data}</h1>
};

switch / case 

조건이 다양하다면 switch / case를 활용 할 수도 있다. 

const Dialog({ type, ...rest }) => {
switch(type) {
case 'share':
return <ShareDialog {...rest} />;
case 'edit':
return <EditDialog {...rest} />;
case 'delete':
return <DeleteDialog {...rest} />;
default:
return null;
}
};

&&, || (Logical AND, Logical OR)

논리 연산자(Logical Operator)를 사용하여 조건부 처리 방법.

const LogicalAnd = ({ username }) => {
return (
<h1>
{username && <span>username</span>}
</h1>
);
};
const LogicalOr = ({ username }) => {
return (
<h1>
{username || 'no username'}
</h1>
);
};

condition ? expr1 : expr2 (Ternary Operator)

삼항 연산자를 사용하여 분기처리 하는 방법.

const TernaryComponent = ({ loading, data }) => {
return {loading ? <LoadingComponent /> : <h1>data</h1>};
};

HOC(Higher Order Component)를 이용한 조건부 렌더링

조건부 렌더링을 담당하는 HOC를 만들어 실제 컴포넌트에서는 조건을 신경쓰지 않고(관심사 분리) 렌더링을 하도록 하면, 컴포넌트 자체의 목적도 더 분명하고 재사용성도 증가 시킬 수 있다.

const Success = () => {
return <h1>good</h1>;
};
const False = () => <h1>condition fail</h1>;
const withCondition = (condition, FalsyComponent) => {
if (condition()) {
return WrappedComponent => WrappedComponent;
}
return () => FalsyComponent;
};
const SuccessWithCondition = withCondition(() => false, False)(Success);

즉시 실행 함수 IIFE(Immediately Invoked Function Expression)를 이용한 방법

IIFE를 활용해서 분기 처리를 할 수도 있다.

const sampleComponent = () => {
return (
<div>
{
(() => {
if (flag && flag2 && !flag3) {
if (flag4) {
return <p>Blah</p>
} else if (flag5) {
return <p>Meh</p>
} else {
return <p>Herp</p>
}
} else {
return <p>Derp</p>
}
})()
}
</div>
)
};

자바스크립트 객체를 활용한 방법

prop의 값이 여러개라면 if / else나 switch / case statement를 사용하기 보다는 객체(object)를 하나 만들어 key(prop value) / value(component)로 만들어 사용하면 코드도 훨씬 깔끔하고 가독성을 높일 수 있다.

import {
SHARE_DIALOG,
CONFIRM_EDIT_DIALOG,
CONFIRM_DELETE_DIALOG,
} from './constants/ui';
import ShareDialog from './ShareDialog';
import ConfirmEditDialog from './ConfirmEditDialog';
import ConfirmDeleteDialog from './ConfirmDeleteDialog';
const DIALOG_COMPONENTS_MAP = {
[SHARE_DIALOG]: ShareDialog,
[CONFIRM_EDIT_DIALOG]: ConfirmEditDialog,
[CONFIRM_DELETE_DIALOG]: ConfirmDeleteDialog,
};
const GlobalDialog = ({ open, onClose, dialogType, dialogProps }) => {
if (!dialogType || !DIALOG_COMPONENTS_MAP[dialogType]) {
return null;
}
const SpecificDialog = DIALOG_COMPONENTS_MAP[dialogType];
return <SpecificDialog {...dialogProps} open={open} onClose={onClose} />;
};

외부 라이브러리를 활용하는 방법

recompose의 branch HOC를 활용한 방법

리액트 유틸리티 라이브러리인 recompose의 branch를 사용하여 분기 처리를 해주는 HOC 함수를 사용 할 수도 있다.

const spinnerWhileLoading = isLoading =>
branch(
isLoading, // boolean(true or false) 값을 리턴하는 함수
renderComponent(Spinner) // 조건식이 true일 때 렌더링
)
const enhance = spinnerWhileLoading(
props => !(props.title && props.author && props.content)
)
// 조건식이 false (isLoading === false)일 때 렌더링
const Post = enhance(({ title, author, content }) =>
<article>
<h1>{title}</h1>
<h2>By {author.name}</h2>
<div>{content}</div>
</article>
)

개인적으로 선호하는 방식은 아니라서 여기서 샘플소스를 다루진 않겠지만, https://github.com/AlexGilleran/jsx-control-statements https://github.com/romac/react-if 등의 외부 라이브러리를 사용하는 방법도 있으니 참고하자.


리액트에서 조건에 따라 다른 컴포넌트를 렌더링 하는 방법에 대해서 알아봤다. 사실, 리액트에서 제공하는 기능이 아닌 자바스크립트에 내장되어 있는 기능/특징을 활용한 방법이라서 특별해 보이진 않을 것이다. 보통 자바스크립트 템플릿 엔진의 경우 자체적으로 조건부 렌더링을 할 수 있는 특수한 문법을 제공하는게 일반적이지만 리액트의 경우 자바스크립트의 순수 기능을 적극 활용 할 수 있도록 설계되어 있다. 이것이 처음 리액트를 접하는 분들에겐 헷갈릴 수 있는 부분이기도 하니 이점을 염두하고 리액트 컴포넌트 개발을 하도록 하자.

더 읽을 거리:



리뷰