React.js

특정한 state 값에 따른 다른 페이지 랜더링을 효율적으로 랜더링 하는 방법에 대해

Dev갱이 2024. 5. 19. 19:10
728x90
const ScheduleSidebar: FC<ScheduleSidebarProps> = ({
	isSelecteGroup,
	isScheduleName,
	isStartEndPeriod,
	isPage,
}) => {
	return (
		<div
			className={cn(styles.right_sidebar_container, {
				[styles.mobile_toruism_sidebar]: isPage === 'tourismPage',
			})}
		>
			{isPage === 'tourismPage' && (
				<SidebarScheduleTourism
					isSelecteGroup={isSelecteGroup}
					isScheduleName={isScheduleName}
					isStartEndPeriod={isStartEndPeriod}
					isPage={isPage}
				/>
			)}
			{isPage === 'periodPage' && <SidebarSharedMembers />}
            ...
            ...
            ...
    		{/* 계속 쭉쭉 늘어날거에요! 가독성이 안좋습니다 */}
		</div>
	);
};

export default ScheduleSidebar;

 

isPage 상태값에 따라 `&&` 연산자를 통해서 다른 컴포넌트를 렌더링 하게끔 만들게 되었을때 가독성이 굉장히 안좋아보인다.

 

// 호출 부모 컴포넌트
<ScheduleSidebarController
    isSelecteGroup={isSelecteGroup}
    isScheduleName={isScheduleName}
    isStartEndPeriod={isStartEndPeriod}
    isPage={isPage}
    status={isPage}
/>

// const 
export const schdulePages = [
	'selectGroupPage',
	'periodPage',
	'tourismPage',
] as const;

// controller를 담당하는 컴포넌트
const StatusScheduleSidebar = {
	[schdulePages[1]]: SidebarSharedMembers,
	[schdulePages[2]]: SidebarScheduleTourism,
};

interface StatusProps extends ScheduleSidebarProps {
	status: (typeof schdulePages)[1 | 2];
}

const ScheduleSidebarController: FC<StatusProps> = ({ status, ...rest }) => {
	if (typeof StatusScheduleSidebar[status] !== 'undefined') {
		return React.createElement(StatusScheduleSidebar[status], rest);
	}
	return <div>오류가 발생했습니다. 고객센터로 문의 바랍니다.</div>;
};

export default ScheduleSidebarController;

 

`createElement`는 첫번째 인자값이 컴포넌트, 두번째 인자값이 props, 세번째 인자값이 children이다.
배열로 const를 선언하여 배열 인덱스 접근법으로 접근하는 방식이 불편하다면 객체 const를 만들어서 사용하면 된다. 아래 예제 참고

 

// const 
export const LayerMode = {
	linkInvite: 'linkInvite',
	emailInvite: 'emailInvite',
	groupDeleteConfirm: 'groupDeleteConfirm',
	createFeed: 'createFeed',
	feedDeleteConfirm: 'feedDeleteConfirm',
	commentDeleteConfirm: 'commentDeleteConfirm',
	logoutConfirm: 'logoutConfirm',
	editProfile: 'editProfile',
	selectedContentType: 'selectedContentType',
	serviceCategory: 'serviceCategory',
	areaCode: 'areaCode',
	tourismDetail: 'tourismDetail',
	scheduleDeleteConfirm: 'scheduleDeleteConfirm',
	scheduleThumbnailImage: 'scheduleThumbnailImage',
} as const;

// controller
const StatusLookUpTable = {
	[LayerMode.emailInvite]: EmailInvite,
	[LayerMode.linkInvite]: LinkInvite,
	[LayerMode.groupDeleteConfirm]: GroupDeleteConfirm,
	[LayerMode.createFeed]: CreateFeed,
	[LayerMode.feedDeleteConfirm]: FeedDeleteConfirm,
	[LayerMode.commentDeleteConfirm]: CommentDeleteConfirm,
	[LayerMode.logoutConfirm]: LogOutConfirm,
	[LayerMode.editProfile]: EditProfile,
	[LayerMode.selectedContentType]: ContentType,
	[LayerMode.serviceCategory]: ServiceCategory,
	[LayerMode.areaCode]: AreaCode,
	[LayerMode.tourismDetail]: TourismDetail,
	[LayerMode.scheduleDeleteConfirm]: ScheduleDeleteConfirm,
	[LayerMode.scheduleThumbnailImage]: ScheduleThumbnailImage,
};

interface StatusProps {
	status: Union<typeof LayerMode>;
}

const LayerModalControll: FC<StatusProps> = ({ status }) => {
	if (typeof StatusLookUpTable[status] !== 'undefined') {
		return React.createElement(StatusLookUpTable[status]);
	}
	return <div>오류가 발생했습니다. 고객센터로 문의 바랍니다.</div>;
};

export default LayerModalControll;
728x90