gpt4 book ai didi

javascript - 按顺序运行定时器 : Reactjs

转载 作者:行者123 更新时间:2023-12-05 04:23:59 25 4
gpt4 key购买 nike

我有一个文件上传组件,它接收要上传的文件列表。我在我实现的 wau 中,这些文件中的每一个都有 thir 计时器并行运行而不影响其他文件。进度条附在每个文件上,它们并行运行直至完成。我想要的是,一旦我选择了文件,我希望每个文件按顺序运行其进度条,而不是一次运行所有进度条。就像拿一个文件,运行它的进度,然后一旦完成,就转到下一个

谁能帮忙

https://codesandbox.io/s/updated-file-upload-4vrnks?file=/src/Upload.tsxfile=/src/Upload.tsx:0-3474

import * as React from "react";
import { Stack, Button, ListItem } from "@material-ui/core";
import { useEffect, useRef } from "react";
import { Progress } from "./Progress";

export interface FileType {
file: File;
isDeleted: boolean;
uploadStatus: number;
uploadError: string;
uploadAbort: boolean;
}

interface FileUploaderProps {
selectedFiles: FileType[];
setSelectedFiles: React.Dispatch<React.SetStateAction<FileType[]>>;
file: FileType;
}

const UploadFile = ({ file, setSelectedFiles }: FileUploaderProps) => {
const timerRef = useRef<ReturnType<typeof setInterval> | undefined>();
const pollRef = useRef<number>();
pollRef.current = file.uploadStatus;

const onFileUpload = () => {
timerRef.current = setInterval(() => {
if (pollRef.current === 100) {
clearInterval(timerRef?.current);
return pollRef?.current;
}
const diff = Math.random() * 15;
let currentProgess = file.uploadStatus;
setSelectedFiles((prevState) => {
return prevState.map((current: FileType) => {
if (current.file.name === file.file.name) {
currentProgess = Math.min(current.uploadStatus + diff, 100);
return {
...current,
uploadStatus: currentProgess
};
}
return current;
});
});
return currentProgess;
}, 100 * Math.floor(Math.random() * 6) + 5 * 50);
};

useEffect(() => {
onFileUpload();
return () => {
clearInterval(timerRef.current);
};
}, []);

const cancelTimer = (e: React.MouseEvent<HTMLSpanElement>) => {
e.stopPropagation();
setSelectedFiles((prevState) => {
return prevState.map((current: FileType) => {
if (current.file.name === file.file.name) {
return {
...current,
uploadAbort: true,
uploadStatus: 0,
uploadError: "File Upload cancelled"
};
}
return current;
});
});
clearInterval(timerRef.current);
};

return (
<ListItem key={file.file.name} className={"file-name"}>
<span style={{ padding: "10px" }}>{file.file.name}</span>
{file.uploadStatus !== 100 ? (
file.uploadError || file.uploadAbort ? (
<div className={"upload-error"}>
<span>{file.file.name}</span>
<span style={{ padding: "10px" }}>{file.uploadError}</span>
</div>
) : (
<>
<span>Uploading...</span>
<Stack sx={{ width: "80px", padding: "20px" }} spacing={2}>
<Progress progress={file.uploadStatus} />
</Stack>
<Button variant="contained" color="error" onClick={cancelTimer}>
Cancel
</Button>
</>
)
) : (
<>
<span className="primary">{file.file.name}</span>
</>
)}
{file.uploadStatus === 100 && (
<Button
variant="contained"
color="error"
className="mgmt-Delete-icon"
style={{ padding: "10px" }}
onClick={(e: React.MouseEvent<HTMLSpanElement>) => {
e.stopPropagation();
setSelectedFiles((prevState) => {
return prevState.map((current: FileType) => {
if (current.file.name === file.file.name) {
return {
...current,
isDeleted: true
};
}
return current;
});
});
}}
>
Delete
</Button>
)}
</ListItem>
);
};

export default UploadFile;

最佳答案

让我们将 active 属性添加到 FileType:

export interface FileType {
...
active: boolean;
}

默认情况下,所有拖放的文件都是不活动

我们希望在文件变为事件时开始上传:

useEffect(() => {
if (file.active) {
onFileUpload();
}
return () => {
clearInterval(timerRef.current);
};
}, [file.active]);

每当 selectedFiles 改变时,我们选择下一个事件文件(或保持当前文件):

useEffect(() => {
const newActiveFile = selectedFiles.find(
(f) =>
!f.isDeleted &&
!f.uploadAbort &&
!f.uploadError &&
f.uploadStatus !== 100
);
if (newActiveFile && !newActiveFile.active) {
setSelectedFiles(
selectedFiles.map((f) =>
f === newActiveFile ? { ...newActiveFile, active: true } : f
)
);
}
}, [selectedFiles]);

Working example

更新

您可以通过将此过滤器添加到 List 来隐藏未启动的文件:

&& file.active

Updated example

关于javascript - 按顺序运行定时器 : Reactjs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73590340/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com