I am having a file uploader which is a child component. The state of the files are being maintained in tha App component. I am trying to mock, the upload and failure cases inside App component itself using setInterval
. But I am using passing a ref from the child component to the parent callback, just so that I get the latest upload status of a file inside setTimeout. Implementation works just fine, Is there someway where I can do all this, without passing down any ref to the parent component inside callback?
I am able to successfully mock the completion and failure. In the below sandbox, I am hardcoding the file name to "1.txt" so that uploads fail just for that.
Note: Its ok if I have to create any ref's inside App, I just dont want the ref to be part of onFileUpload
callback when passed to the App component
Sandbox: https://codesandbox.io/s/updated-file-upload-forked-k59xgo
Inside File Upload
const timerRef = useRef<ReturnType<typeof setInterval> | undefined>();
useEffect(() => {
if (file.active && !file.uploadError) {
onFileUpload(file, timerRef);
}
}, [file.active, file, onFileUpload]);
Inside App
const onFileUpload = (
selectedFile: FileType,
uploadRef: React.MutableRefObject<
ReturnType<typeof setInterval> | undefined
>
) => {
pollRef.current = selectedFile;
if (!uploadRef.current) {
uploadRef.current = setInterval(() => {
if (
pollRef.current?.uploadStatus === 100 ||
pollRef.current?.uploadError
) {
clearInterval(uploadRef.current);
}
const diff: number = Math.random() * 15;
let currentProgess: number = pollRef.current?.uploadStatus as number;
setSelectedFiles((prevState: FileType[]) => {
return prevState.map((currentFile: FileType) => {
const {
file: { name: currentFileName },
uploadStatus: currentFileUploadStatus
} = currentFile;
if (currentFileName === selectedFile.file.name) {
if (
selectedFile.file.name === "1.pdf" &&
currentFileUploadStatus > 40
) {
clearInterval(uploadRef.current);
return {
...currentFile,
uploadStatus: 0,
isActive: true,
uploadError: "Upload Error"
};
}
currentProgess = Math.min(currentFileUploadStatus + diff, 100);
return {
...currentFile,
uploadStatus: currentProgess
};
} else return currentFile;
});
});
return currentProgess;
}, 60 * Math.floor(Math.random() * 6) + 100);
}
};
You already use the file name as key for React.
<ListItem key={file.file.name} className={"file-name"}>
You could also use it as a key for the timeouts.
Effectively, that's what already happens. You rely on React rendering your unique component to get the right timeout reference.
This allows you to remove uploadRef
, also from the UploadFile
component as it was only used for this timeout.
const fileIntervals = useRef({});
const onFileUpload = ( selectedFile: FileType ) => {
// ...
const { name } = selectedFile;
if (fileIntervals.current[name]) {
return;
}
fileIntervals.current[name] = setInterval( // ...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.