uppy pauseResume throw unhandled error
AhmadKajjan-QU opened this issue · comments
Initial checklist
- I understand this is a bug report and questions should be posted in the Community Forum
- I searched issues and couldn’t find anything (or linked relevant results below)
Link to runnable example
Uppy React
Steps to reproduce
this is my context code
I was trying to add a resume and pause feature of a file.
import React, { createContext, useContext, useState, useEffect } from "react";
import Uppy from "@uppy/core";
import Tus from "@uppy/tus";
import { calculateFileHash, handleError } from "../utils/functions";
import { useFilesBackend } from "../hooks/useFileBackend";
import { toast } from "react-toastify";
import { UploadData } from "../types";
import { backendEndpoint } from "../config";
import Cookies from "js-cookie";
import { useUser } from "./UserContext";
type UploadContextType = {
uploads: UploadData[];
canUpload: boolean;
addUpload: (userId: string, files: FileList) => void;
pauseUpload: (filename: string) => void;
resumeUpload: (filename: string) => void;
};
const UploadContext = createContext<UploadContextType | undefined>(undefined);
export const useUploads = () => {
const context = useContext(UploadContext);
if (!context) {
throw new Error("useUploads must be used within an UploadProvider");
}
return context;
};
export const UploadProvider: React.FC<any> = ({ children }) => {
const [uploads, setUploads] = useState<UploadData[]>([]);
const [canUpload, setCanUpload] = useState<boolean>(true);
const { signFiles, setFileUploadingTimeout } = useFilesBackend();
const {
user: { id: userId },
} = useUser();
// Initialize Uppy
const uppy = new Uppy({
autoProceed: false,
allowMultipleUploads: true,
restrictions: {
maxNumberOfFiles: 10,
},
}).use(Tus, {
endpoint: `${backendEndpoint}/uploads`,
headers: {
Authorization: `Bearer ${Cookies.get("sheelToken")}`,
},
retryDelays: [0, 1000, 3000, 5000],
});
const addUpload = async (userId: string, files: FileList) => {
if (!canUpload) return;
try {
setCanUpload(false);
const filesArray: File[] = [...files];
const newUploads: UploadData[] = filesArray.map((file) => ({
filename: file.name,
file,
fileHash: "",
progress: 0,
error: null,
complete: false,
isPaused: false,
status: "Preparing Files",
instance: null,
}));
setUploads((uploads) => [...uploads, ...newUploads]);
const calculatedUploads = await Promise.all(
newUploads.map(async (upload, idx) => {
return {
...upload,
fileHash: await calculateFileHash(files[idx]),
status: "Waiting Approval",
};
})
);
console.log("calculated", calculatedUploads);
setUploads([...calculatedUploads]);
await startUploading(calculatedUploads);
} catch (error) {
console.error(error);
setCanUpload(true);
}
};
const startUploading = async (itemsToUploads: UploadData[]) => {
try {
const filesToSend = itemsToUploads
.filter((upload) => upload.status === "Waiting Approval")
.map((upload) => upload.file);
await signFiles(
filesToSend,
itemsToUploads.map((upload) => upload.fileHash)
);
await uploadFiles(itemsToUploads);
} catch (error) {
toast.error(handleError(error));
setUploads([]);
setCanUpload(true);
}
};
const updateUpload = (
filename: string,
updater: (u: UploadData) => UploadData
) => {
setUploads((uploads) =>
uploads.map((upload) => {
if (upload.filename === filename) {
return updater(upload);
}
return upload;
})
);
};
const pauseUpload = (filename: string) => {
updateUpload(filename, (u) => {
console.log("pausing", filename, u.id);
if (u.id) {
uppy.pauseResume(u.id); // Pause specific file upload
return {
...u,
isPaused: true,
status: "Paused",
};
} else return u;
});
};
const resumeUpload = (filename: string) => {
updateUpload(filename, (u) => {
if (u.id && u.isPaused) {
uppy.pauseResume(u.id); // Pause specific file upload
return {
...u,
isPaused: false,
status: "Uploading",
};
} else return u;
});
};
const uploadFiles = (itemsToUploads: UploadData[]) => {
itemsToUploads.forEach((item) => {
const { file, filename, fileHash } = item;
const id = uppy.addFile({
name: filename,
type: file.type,
data: file,
meta: {
fileHash: item.fileHash,
userId: userId,
},
});
const intervalId = setInterval(
() => setFileUploadingTimeout(fileHash),
5 * 60 * 1000
);
updateUpload(filename, (u) => ({
...u,
id,
intervalId,
}));
});
uppy.upload();
};
useEffect(() => {
uppy.on("upload-progress", (file: any, progress) => {
const percentage = (progress.bytesUploaded / progress.bytesTotal) * 100;
updateUpload(file.name, (u) => ({
...u,
progress: percentage,
status: "Uploading",
}));
});
uppy.on("upload-success", (file: any) => {
updateUpload(file.name, (u) => {
clearInterval(u.intervalId);
return {
...u,
complete: true,
status: "Complete",
};
});
// uploadChunkCompleted(file.meta.fileHash, file.name, file.data.size, 0);
console.log("Upload complete:", file.uploadURL);
});
uppy.on("upload-error", (file: any) => {
updateUpload(file.name, (u) => {
clearInterval(u.intervalId);
return {
...u,
complete: true,
status: "Failed",
};
});
});
uppy.on("error", (error) => {
console.error("Failed to upload:", error);
toast.error(handleError(error));
});
if (
uploads.reduce((acc, curr) => acc + (curr.complete ? 1 : 0), 0) ===
uploads.length
) {
setCanUpload(true);
}
}, [uploads, uppy, updateUpload]);
return (
<UploadContext.Provider
value={{ uploads, canUpload, addUpload, pauseUpload, resumeUpload }}
>
{children}
</UploadContext.Provider>
);
};
I got the following error when try to pause
Cannot read properties of undefined (reading 'progress')
TypeError: Cannot read properties of undefined (reading 'progress')
at Uppy.pauseResume (http://localhost:3000/static/js/bundle.js:125589:79)
at http://localhost:3000/static/js/bundle.js:7731:14
at http://localhost:3000/static/js/bundle.js:7722:16
at Array.map (<anonymous>)
at http://localhost:3000/static/js/bundle.js:7720:35
at basicStateReducer (http://localhost:3000/static/js/bundle.js:64835:45)
at updateReducer (http://localhost:3000/static/js/bundle.js:64944:26)
at updateState (http://localhost:3000/static/js/bundle.js:65230:14)
at Object.useState (http://localhost:3000/static/js/bundle.js:66027:20)
at useState (http://localhost:3000/static/js/bundle.js:87999:25)`
am I making any thing wrong
Expected behavior
The file should get paused
Actual behavior
I got this unhandled error
Cannot read properties of undefined (reading 'progress')
TypeError: Cannot read properties of undefined (reading 'progress')
at Uppy.pauseResume (http://localhost:3000/static/js/bundle.js:125589:79)
at http://localhost:3000/static/js/bundle.js:7731:14
at http://localhost:3000/static/js/bundle.js:7722:16
at Array.map ()
at http://localhost:3000/static/js/bundle.js:7720:35
at basicStateReducer (http://localhost:3000/static/js/bundle.js:64835:45)
at updateReducer (http://localhost:3000/static/js/bundle.js:64944:26)
at updateState (http://localhost:3000/static/js/bundle.js:65230:14)
at Object.useState (http://localhost:3000/static/js/bundle.js:66027:20)
at useState (http://localhost:3000/static/js/bundle.js:87999:25)
I make uppy as a Ref and it worked
Please read the uppy react docs carefully. Do not put Uppy inside the component as a simple variable or ref.