Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions packages/components/upload/hooks/useUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ export default function useUpload(props: TdUploadProps) {
const [sizeOverLimitMessage, setSizeOverLimitMessage] = useState('');
const [update, forceUpdate] = useState({});

// 标记 setUploadValue 是否由组件内部主动触发
// - true:内部调用(如选择文件、上传成功、onRemove 等),不需要进行外部清空联动
// - false:外部主动修改 props.files,需要联动清空 toUploadFiles
const internalUpdateRef = useRef(false);
const updateInternalValue: typeof setUploadValue = (value, ...args) => {
internalUpdateRef.current = true;
setUploadValue(value, ...args);
};

const locale = useMemo(() => merge({}, globalLocale, props.locale), [globalLocale, props.locale]);

const tipsClasses = `${classPrefix}-upload__tips ${classPrefix}-size-s`;
Expand Down Expand Up @@ -88,7 +97,7 @@ export default function useUpload(props: TdUploadProps) {
if (props.autoUpload) {
setToUploadFiles([...toFiles]);
} else {
setUploadValue([...uploadValue], {
updateInternalValue([...uploadValue], {
e: p.event,
trigger,
index: uploadValue.length,
Expand Down Expand Up @@ -146,7 +155,7 @@ export default function useUpload(props: TdUploadProps) {
const handleNotAutoUpload = (toFiles: UploadFile[]) => {
const tmpFiles = props.multiple && !isBatchUpload ? uploadValue.concat(toFiles) : toFiles;
if (!tmpFiles.length) return;
setUploadValue(tmpFiles, {
updateInternalValue(tmpFiles, {
trigger: 'add',
index: uploadValue.length,
file: toFiles[0],
Expand Down Expand Up @@ -290,7 +299,7 @@ export default function useUpload(props: TdUploadProps) {
}).then(({ status, data, list, failedFiles }) => {
setUploading(false);
if (status === 'success') {
setUploadValue([...data.files], {
updateInternalValue([...data.files], {
trigger: 'add',
file: data.files[0],
});
Expand Down Expand Up @@ -336,16 +345,16 @@ export default function useUpload(props: TdUploadProps) {
// remove all files for batchUpload
if (isBatchUpload || !props.multiple) {
props.onWaitingUploadFilesChange?.({ files: [], trigger: 'remove' });
setUploadValue([], changePrams);
updateInternalValue([], changePrams);
setToUploadFiles([]);
xhrReq.current = [];
} else if (!props.autoUpload) {
uploadValue.splice(p.index, 1);
setUploadValue([...uploadValue], changePrams);
updateInternalValue([...uploadValue], changePrams);
} else if (p.index < uploadValue.length) {
// autoUpload 场景下, p.index < uploadValue.length 表示移除已经上传成功的文件;反之表示移除待上传列表文件
uploadValue.splice(p.index, 1);
setUploadValue([...uploadValue], changePrams);
updateInternalValue([...uploadValue], changePrams);
} else {
const tmpFiles = [...toUploadFiles];
tmpFiles.splice(p.index - uploadValue.length, 1);
Expand All @@ -371,7 +380,7 @@ export default function useUpload(props: TdUploadProps) {
if (autoUpload) {
setToUploadFiles([]);
} else {
setUploadValue(
updateInternalValue(
uploadValue.map((item) => {
if (item.status !== 'success') {
return { ...item, status: 'waiting' };
Expand All @@ -392,7 +401,23 @@ export default function useUpload(props: TdUploadProps) {
// 矫正数据格式为数组
useEffect(() => {
if (!Array.isArray(uploadValue)) {
setUploadValue([], { trigger: 'default' });
updateInternalValue([], { trigger: 'default' });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [uploadValue]);

useEffect(() => {
// 监听受控值 props.files 的引用变化:
// - 若变化由组件内部触发(internalUpdateRef === true),消费标记后跳过
// - 若变化由外部主动触发且新值为空数组,则同步清空内部维护的 toUploadFiles,确保失败/等待的文件能被一起清除
if (internalUpdateRef.current) {
internalUpdateRef.current = false;
return;
}
const currentLen = Array.isArray(uploadValue) ? uploadValue.length : 0;
if (currentLen === 0 && toUploadFiles.length > 0) {
setToUploadFiles([]);
props.onWaitingUploadFilesChange?.({ files: [], trigger: 'remove' });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [uploadValue]);
Expand Down
Loading