This content originally appeared on DEV Community and was authored by Yoav Niran
<Intro>
Building a file-upload UI that both looks great and includes features such as: progress indication, cancel uploads, and resume failed uploads, may sound difficult to do. In this article I'd like to dispel this notion and show that in fact can be a breeze.
To achieve said target we'll look into using And Design and React-Uploady.
Ant Design is a great library for UI components. React-Uploady provides excellent building blocks and a lot of functionality for client-side file uploading.
Disclaimer: I'm the creator of React-Uploady
If you're unfamiliar with React-Uploady, I recommend starting at:
react-uploady: uploading files in React
Yoav Niran ・ May 6 '20 ・ 3 min read
The following code example shows how to render an upload queue using UI components from Ant Design (Button, Card, Progress, etc.).
I'll keep the Uploady part simple for the sake of the example but the there's nothing preventing us from using any of its more sophisticated and advanced features/capabilities.
Here's the end result we'll be building toward:
The UI itself may not fit exactly what you're building in your own app, but it demonstrates how easy it is to integrate these two libraries. It was literally a matter of minutes to hook up (and I've never used Ant). If you're using Ant or planning to along with file-upload functionality, you're in luck ?.
</Intro>
<Code>
import Uploady from "@rpldy/uploady";
import retryEnhancer from "@rpldy/retry-hooks";
const App = () => {
return (
<div className="App">
<Uploady
destination={{ url: "my-server.com/upload" }}
enhancer={retryEnhancer}>
<UploadUi />
</Uploady>
</div>
);
};
In the code above we're setting up the scene, initializing Uploady and rendering the rest of our app.
Notice
We use retryEnhancer to enable upload retry functionality. This isn't mandatory of course but is important as it makes it possible for users to retry failed/aborted uploads.
import { asUploadButton } from "@rpldy/upload-button";
import { Button, PageHeader, Layout } from "antd";
const UploadButton = asUploadButton(Button);
const UploadUi = () => {
const previewMethodsRef = useRef();
const [previews, setPreviews] = useState([]);
const onClearPreviews = useCallback(() => {
previewMethodsRef.current?.clear();
}, [previewMethodsRef]);
return (
<Layout>
<PageHeader
title="File Upload"
subTitle="Powered by: React Uploady + Ant Design"
extra={[
<UploadButton
key="upload-button"
extraProps={{
type: "primary",
size: "large",
icon: <CloudUploadOutlined />
}}
/>,
<Button
key="clear-button"
icon={<DeleteOutlined />}
size="large"
disabled={!previews.length}
onClick={onClearPreviews}
>
Clear
</Button>
]}
/>
<Layout.Content>
<UploadPreviewCards
setPreviews={setPreviews}
previewMethodsRef={previewMethodsRef}
/>
</Layout.Content>
<Layout.Footer>Previews Shown: {previews.length}</Layout.Footer>
</Layout>
);
};
This is our main UI component, rendering our layout, upload button and previews.
Notice
First thing is we wrap Ant's Button component with Uploady's asUploadButton. This makes it into an Upload Button that will open the file dialog when clicked. Ant specific props are passed using the extraProps
prop.
We define previewMethodsRef
that is later passed to the UploadPreview Uploady component. It's defined here so we can access the preview API (clear previews method) in this component. More on this later.
import UploadPreview from "@rpldy/upload-preview";
import { Row } from "antd";
const UploadPreviewCards = ({ previewMethodsRef, setPreviews }) => {
const getPreviewProps = useCallback(
(item) => ({ id: item.id, name: item.file.name }),
[]
);
return (
<Row gutter={2} justify="center" className="preview-row">
<UploadPreview
previewComponentProps={getPreviewProps}
PreviewComponent={PreviewCard}
onPreviewsChanged={setPreviews}
previewMethodsRef={previewMethodsRef}
rememberPreviousBatches
/>
</Row>
);
};
Here we render Uploady's UploadPreview component that makes it easy to add image (and video) previews once upload begins.
Notice
previewComponentProps
makes it possible to define which props the custom preview component will receive.
PreviewComponent
is our custom preview component that will be rendered for each file being uploaded.
onPreviewsChanged
is a callback called when previews are added/removed. We use it to change the state and make it possible to show the number of previews shown (by the parent component in this case).
previewMethodsRef
is a React ref that will receive the clear previews method that is used by the parent component (in this case).
rememberPreviousBatches
instructs the preview component to keep the previews from previous batches.
import {
useItemProgressListener,
useItemFinalizeListener,
useItemAbortListener,
useAbortItem
} from "@rpldy/uploady";
import retryEnhancer, { useRetry } from "@rpldy/retry-hooks";
import { Button, Card, Col, Row, Progress, PageHeader, Layout } from "antd";
const STATES = {
PROGRESS: "PROGRESS",
DONE: "DONE",
ABORTED: "ABORTED",
ERROR: "ERROR"
};
const isItemError = (state) =>
state === STATES.ABORTED || state === STATES.ERROR;
const PreviewCard = memo(({ id, url, name }) => {
const [percent, setPercent] = useState(0);
const [itemState, setItemState] = useState(STATES.PROGRESS);
const abortItem = useAbortItem();
const retry = useRetry();
useItemProgressListener((item) => {
setPercent(item.completed);
}, id);
useItemFinalizeListener((item) => {
setItemState(
item.state === "finished"
? STATES.DONE
: item.state === "aborted"
? STATES.ABORTED
: STATES.ERROR
);
}, id);
useItemAbortListener(() => {
setItemState(STATES.ABORTED);
}, id);
const onAbort = useCallback(() => {
abortItem(id);
}, [abortItem, id]);
const onRetry = useCallback(() => {
retry(id);
}, [retry, id]);
return (
<Col gutter={2}>
<Card
hoverable
style={{ width: 240 }}
cover={<img alt="example" src={url} />}
actions={[
<Button
key="stop"
icon={<StopOutlined />}
onClick={onAbort}
disabled={itemState !== STATES.PROGRESS}
type="link"
/>,
<Button
key="retry"
icon={<RedoOutlined />}
onClick={onRetry}
disabled={!isItemError(itemState)}
type="link"
/>
]}
>
<Card.Meta
title={name}
description={
<Progress
type="dashboard"
percent={percent}
width={66}
strokeColor={
isItemError(itemState)
? "#FF4D4F"
: {
"0%": "#108ee9",
"100%": "#87d068"
}
}
status={isItemError(itemState) ? "exception" : undefined}
/>
}
/>
</Card>
</Col>
);
});
The Preview Card makes use of different Uploady hooks as well as very useful components from Ant.
Notice
useItemProgressListener is used to get updates on the upload progress for the item being uploaded (we pass the id as the hook's second param so it's only called for the specific item).
useItemFinalizeListener and useItemAbortListener are used to set the state of the item (ex: success, failed, etc.).
useRetry is used to access the retry method and call it (only) on failed items.
useAbortItem is used to access the abort method and call it in order to cancel an upload before it completes.
Ant's Card component comes in handy for our purpose. It shows the image being uploaded (using the cover
prop), shows textual information and action buttons that provide the user with the ability to abort/retry.
Ant's Progress component has a "dashboard" variant that looks cool inside the preview card. It accepts a strokeColor
prop that makes the item's upload status clearly visible.
</Code>
<Conclusion>
Working code for this post can be found in this sandbox:
Uploady's approach to UI is to be as minimalist as possible. To do what it does best (upload files), while letting developers build their presentation on top of it in any way they like.
Ant Design is a great library for UI components and (from my limited experience) seems very easy to use with plenty of options and features.
Combining the two felt very natural and easy. Hopefully this post comes in handy for you if you're looking to add file-upload capabilities to your application that look great.
</Conclusion>
This content originally appeared on DEV Community and was authored by Yoav Niran
Yoav Niran | Sciencx (2021-04-29T09:39:00+00:00) React Uploady with Ant Design. Retrieved from https://www.scien.cx/2021/04/29/react-uploady-with-ant-design/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.