ソースを参照

🐛 fix(image-selector): 修复图片选择器无限循环问题

- 添加useRef跟踪selectedFiles历史值,避免依赖数组变化触发的无限循环
- 实现数组内容比较函数,判断实际内容变化而非引用变化
- 优化useEffect依赖数组,移除localSelectedFiles依赖
- 重构对话框打开时的状态初始化逻辑,区分单选/多选场景
yourname 4 ヶ月 前
コミット
bb1c578e31
1 ファイル変更22 行追加7 行削除
  1. 22 7
      src/client/admin-shadcn/components/ImageSelector.tsx

+ 22 - 7
src/client/admin-shadcn/components/ImageSelector.tsx

@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from 'react';
+import React, { useState, useEffect, useRef } from 'react';
 import { useQuery } from '@tanstack/react-query';
 import { Button } from '@/client/components/ui/button';
 import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/client/components/ui/dialog';
@@ -50,6 +50,7 @@ export const ImageSelector: React.FC<ImageSelectorProps> = ({
   const [isOpen, setIsOpen] = useState(false);
   const [selectedFile, setSelectedFile] = useState<FileType | null>(null);
   const [localSelectedFiles, setLocalSelectedFiles] = useState<number[]>(selectedFiles);
+  const prevSelectedFilesRef = useRef(selectedFiles);
 
   // 获取当前选中的文件详情
   const { data: currentFile } = useQuery({
@@ -63,19 +64,33 @@ export const ImageSelector: React.FC<ImageSelectorProps> = ({
     enabled: !!value,
   });
 
+  
   // 当对话框打开时,设置当前选中的图片
   useEffect(() => {
-    if (isOpen && value && currentFile && (!selectedFile || selectedFile.id !== currentFile.id)) {
-      setSelectedFile(currentFile);
+    if (isOpen) {
+      if (allowMultiple) {
+        setLocalSelectedFiles(selectedFiles);
+      } else if (value && currentFile) {
+        setSelectedFile(currentFile);
+      }
     }
-  }, [isOpen, value, currentFile, selectedFile]);
+  }, [isOpen, value, currentFile, allowMultiple]);
+
 
-  // 当allowMultiple模式下的selectedFiles变化时
+  // 修复无限循环问题:使用ref比较数组内容
   useEffect(() => {
-    if (JSON.stringify(localSelectedFiles) !== JSON.stringify(selectedFiles)) {
+    const areArraysEqual = (a: number[], b: number[]) => {
+      if (a.length !== b.length) return false;
+      const sortedA = [...a].sort();
+      const sortedB = [...b].sort();
+      return sortedA.every((val, index) => val === sortedB[index]);
+    };
+    
+    if (!areArraysEqual(prevSelectedFilesRef.current, selectedFiles)) {
       setLocalSelectedFiles(selectedFiles);
+      prevSelectedFilesRef.current = selectedFiles;
     }
-  }, [selectedFiles, localSelectedFiles]);
+  }, [selectedFiles]);
 
   // 获取图片列表
   const { data: filesData, isLoading, refetch } = useQuery({