서론
React 기반으로 백오피스 구축하다보면 빠른 개발을 위해 ant.design을 사용하는 경우가 종종있다.
빠르게 사용하기위해 제공되는 디자인을 이용하지만, 간혹 커스텀이 필요한 경우도 발생한다.
ant.design 에 문서가 잘 나와있지만, 나중에 참고하기위해 정리하고자한다.
최신버전이 아닌 4.1x 버전의 라이브러리를 사용하고있다.
기본 antd Upload.Dragger는 파일업로드 폼과, 파일 리스트 폼 구조가 따로있다.
자사에서 사용중인 화면은 단건 업로드로, 업로드 후 업로드폼이 사라지고 파일리스트가 나타나야하기때문에 그부분도 추가 작업했다.

antd 속성을 이용한 커스텀과, itemRender에서 직접커스텀하는 두가지 방식으로 정리 했으며, 카드형 타입으로 사용
#0. 실행환경
- react 17 버전의 운영중인 프로젝트
- antd: 4.18.x (4.2x 버전과도 조금씩 다름)
- typescript: 4.5
#1. antd에서 제공하능 속성만을 이용한 방법


antd 의 여러속성을 이용하는 커스텀 코드는 아래와 같음
import { Upload } from "antd";
import { UploadProps } from "antd/es/upload/interface";
interface UploadDraggerFormProps extends UploadProps {}
export const UploadDraggerForm: React.FC<UploadDraggerFormProps> = ({
...props
}) => {
return (
<Upload.Dragger
listType="picture"
iconRender={() => (
// 파일 리스트 아이콘 - 기본; 이미지 아이콘
<IconForm
component={GhostOrderList}
color={color.gray4}
style={{ fontSize: 30 }}
/>
)}
showUploadList={{
showRemoveIcon: true,
showDownloadIcon: false,
showPreviewIcon: false,
removeIcon: (
// 삭제아이콘 - 기본; 휴지통
<IconForm
component={GhostClose}
style={{ fontSize: 10, height: 30 }}
/>
),
}}
progress={{
showInfo: false,
strokeColor: {
from: color.green6,
to: color.green2,
},
strokeWidth: 3,
}}
// height, style은 업로드 직후 업로드 폼 숨기는 용
height={props.fileList?.length ? 0 : undefined}
style={{
visibility: props.fileList?.length ? "hidden" : "visible",
background: "transparent",
}}
{...props}
/>
);
};
- iconRender: 파일리스트의 아이콘 커스텀 속성
- @ant-design/icon 을 바로 사용하면 세부적인 디자인 수정없이 용이
- 자사 아이콘컴포넌트를 사용하게되어 antd Icon component를 커스텀하여 사용 중
- showUploadList: 파일리스트의 세부적인 옵션 제어용으로 각 아래 세 조건에 대하여 show(boolean) 과 icon 속성을 부여
- preview: 미리보기 아이콘 표출 여부 및 미리보기 아이콘 변경 (이미지의 경우 미리보기 가능)
- remove: 삭제 아이콘 표출여부 및 아이콘 변경 (리스트 우측 아이콘)
- download: 다운로드 아이콘 표출여부 및 아이콘변경 (remove 옆에 위치할 수 있음)
- progress: 업로드 중 진행도 표출 (옵셔널)
- antd. progress compoenent 속성을 사용할 수 있음
- 자사에서는 해당업로드를 xlsx 일괄업로드를 위해 작업하기때문에 파일 자체의 업로드상태보다, 비동기로 받는 task-job 진행도로 사용할 예정
- height & style : 파일 업로드 후 업로드화면 숨기는 용
#2. antd upload itemRender 속성을 이용한 커스텀
파일 아이템카드안에는 '아이콘|이미지' - '파일명' - ('다운로드 기능') - '삭제 아이콘' 그리고 프로그래스바로 구성되어있으나, 디자이너가 원하는 업로드 구조는 아래 이미지와 같아서, itemRender와 다른 and 컴포넌트를 이용하여 작업함.
다운로드 버튼 위치에 다운로드 기능 대신 업로드 상태와 파일크기를 추가

아이템 하나의 컴포넌트 코드는 아래와 같음 (itemRender 함수 리턴값)
import { Col, Progress, Row, Space, Typography } from "antd";
import { UploadFile } from "antd/lib/upload/interface";
import { useMemo } from "react";
// antd 4.18.x 에서 itemRenderProps 대신 직접 호출
interface CustomUploadItemRenderPropes {
originNode: React.ReactElement; // 기존 노드아이템 #1. 속성을 이용한디자인 폼이 담김)
file?: UploadFile; // 업로드된 해당 파일정보
fileList?: UploadFile[]; // 다건일경우 요 데이터를 활용하여 리스트화 시킬 수 있을 듯함.
actions?: { // antd 업로드에서 제공하는 아이템 메소드
download: () => void; // 다운로드 함수 호출
preview: () => void; // 미리보기 함수 소출
remove: () => void; // 삭제 함수 호출
};
}
/**
* 파일업로드 화면 커스텀
* @notice 현재 단건만 진행중이라 단건용 컴포 작업
* @param param0
* @returns
*/
export const CustomUploadItemRender: React.FC<CustomUploadItemRenderPropes> = ({
originNode,
file,
fileList,
actions,
}) => {
/**
* 업로드 상태 Dom
*/
const status = useMemo(() => {
switch (file?.status) {
case "uploading": // 진행 중일땐, 진행중 아이콘 표출 (spin 으로 애니메이션화)
return {
icon: <IconForm component={GhostLoading} spin />,
title: (
<Typography.Text style={{ color: color.gray2 }}>
진행 중
</Typography.Text>
),
};
case "error": // 실패의 경우 실패 아이콘
return {
icon: <IconForm component={SolidAlert} color={color.red3} />,
title: (
<Typography.Text style={{ color: color.red3 }}>
업로드 실패
</Typography.Text>
),
};
case "success": // 성공, 완료일 경우 해당 아이콘
case "done":
return {
icon: <IconForm component={SolidCheck} color={color.primary3} />,
title: (
<Typography.Text style={{ color: color.gray4 }}>
업로드 완료
</Typography.Text>
),
};
default: { // 그 외 숨김
return undefined;
}
}
}, [file]);
/**
* 업로드 진척도 및 상태에따라 디자인 처리
*/
const progress = useMemo(() => {
switch (file?.status) {
case "uploading": // 업로드 중이면, 현재 받고있는 퍼센트 전달 - 색상 검정색
return {
percent: file?.percent,
strokeColor: color.gray2,
};
case "error": // 에러면 퍼센트 100, 색상 빨강
return {
percent: 100,
strokeColor: color.red2,
};
case "success": // 성공했으면 퍼센트 100, 색상 초록
return {
percent: 100,
strokeColor: color.green2,
};
default: // 그 외는 숨김 ('done'의 경우는 프로그래스바 없이 성공 상태만 표출)
return {
percent: 0,
strokeColor: gray2,
};
}
}, [file]);
return (
<UploadItemCard bordered bodyStyle={{ padding: 12 }}>
<Row align="middle" gutter={10} wrap={false}>
{/* 파일 아이템 아이콘 - 너비 고정 */}
<Col flex="none">
<IconForm
component={GhostFile}
color={color.gray4}
style={{ fontSize: 24 }}
/>
</Col>
{/* 파일 명 및 업로드 상태, 사이즈 표출 - 너비 full */}
<Col flex="auto">
<Space
align="center"
style={{ display: "flex", justifyContent: "space-between" }}
>
{/* 파일명 위치 */}
<Typography.Text
style={{ lineHeight: "24px", wordBreak: "break-all" }}
>
{file?.name || ""}
</Typography.Text>
{/* 업로드 상태 위치 */}
<Space size={10} align="center">
<Space size={4}>
{status?.icon}
{status?.title}
</Space>
{/* 파일 사이즈 위치 */}
<Typography.Text
style={{
color: color.gray5,
fontWeight: 400,
lineHeight: "24px",
wordBreak: "break-all",
}}
>
{formatBytes(file?.size, 1)}
</Typography.Text>
</Space>
</Space>
</Col>
{/* 파일 아이템 삭제 아이콘 - 너비 고정 */}
<Col flex="none" style={{ display: "flex" }}>
<IconForm
component={GhostClose}
style={{ fontSize: 10 }}
onClick={actions?.remove}
/>
</Col>
</Row>
{/* 업로드 진행 프로그래스바 */}
{["uploading", "success", "error"].includes(file?.status || "") && (
<Progress {...progress} showInfo={false} strokeWidth={4} />
)}
</UploadItemCard>
);
};
- originNode: 기존 노드아이템 #1. 속성을 이용한디자인 폼이 담김)
- file: 업로드된 해당 파일정보
- fileList: 다건일경우 요 데이터를 활용하여 리스트화 시킬 수 있을 듯함.
- actions: antd 업로드에서 제공하는 아이템 메소드
- download: () => void; // 다운로드 함수 호출
- preview: () => void; // 미리보기 함수 소출
- remove: () => void; // 삭제 함수 호출
위에서 만든 아이템 컴포넌트는 Upload.dragger에서 아래와 같이 호출할 수 있음
import { Upload } from "antd";
import { UploadProps } from "antd/es/upload/interface";
interface UploadDraggerFormProps extends UploadProps {}
/**
* dragger upload 기본 폼
* - 디자인 공통 처리 - 카드형식
* @param param0
* @returns
*/
export const UploadDraggerForm: React.FC<UploadDraggerFormProps> = ({
...props
}) => {
return (
<Upload.Dragger
listType="picture"
// 아이템 렌더에 커스텀한 컴포넌트 전달
itemRender={(originNode, file, fileList, actions) => (
<CustomUploadItemRender
originNode={originNode}
file={file}
actions={actions}
/>
)}
{...props}
/>
);
};
#link
- antd 4x upload : https://4x.ant.design/components/upload/#API
Upload - Ant Design
beforeUpload only prevent upload behavior when return false or reject promise, the prevented file would still show in file list. Here is the example you can keep prevented files out of list by return UPLOAD.LIST_IGNORE.
4x.ant.design
'Dev-FE' 카테고리의 다른 글
[WEB] #4. 캔버스 이미지 처리 (1) | 2024.03.18 |
---|---|
[JS,TS] 파일 사이즈 단위 변환 (0) | 2024.03.12 |
[React-Native] #2. React Native - navigation 이용한 페이지 이동 (0) | 2022.10.30 |
[React-Native] #1. React Native 프로젝트 첫 시작하기 (0) | 2022.10.19 |
[WEB] #3. tslint 로 코드 문법 설정하기 (1) | 2022.09.29 |