You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

删除数组元素时useCallback失效,选中图片样式丢失问题

问题描述

点击图标删除图片时,和待删图片同属一个数组的已选中图片会丢失选中样式,尝试用useCallback解决但无效。

原代码

import uuid from "react-uuid";

const [image, setImage] = useState<Blob[]>([]);
const [selectedImage, setSelectedImage] = useState<Blob | null>(null);

const deleteImage = (singleImage: Blob) => {
  const filteredList = Array.from(image).filter(function (img) {
    return img !== singleImage;
  });
  setImage(filteredList);
};

const memoCall = useCallback((img: Blob) => {
  console.log("memoCall");
  if (selectedImage === img) {
    setSelectedImage(null);
  } else {
    setSelectedImage(img);
  }
}, [selectedImage]);

return (
  {image?.length > 0 &&
    image.map((img, index) =>
      selectedImage === img ? (
        <div
          className="w-full h-[300px] relative border-red-500 border-4"
          key={uuid()}
          onClick={() => memoCall(img)}
        >...</div>
      ) : (
        <div
          className="w-full h-[300px] relative"
          key={uuid()}
          onClick={() => memoCall(img)}
        >...</div> 
      )
    )
  }
);
问题根源
  1. key值不稳定:用uuid()作为元素key,每次组件渲染都会生成新的key,React会把每个图片元素当成全新组件重新挂载,之前的选中状态关联直接失效,样式自然丢失。
  2. 删除逻辑未处理选中状态:删除图片时,如果选中的是其他图片,虽然selectedImage的引用还在,但组件重新挂载后,React无法匹配到对应元素,导致样式不生效;如果删除的是选中图片,也没有主动清空选中状态。
  3. useCallback无法解决核心问题:当前memoCall的依赖只有selectedImage,但函数的稳定性无法抵消key值不稳定带来的组件重新挂载问题。
解决方案

1. 改用稳定的key值

不要用动态生成的uuid(),可以给每个图片对象添加唯一标识(比如上传时生成id,存成{id: string, blob: Blob}的结构),或者在图片顺序固定的场景下用数组index。

2. 完善删除逻辑

删除图片时,检查当前选中的图片是否在被删除的列表里,如果是,主动清空选中状态;如果是其他图片,确保选中状态能正确关联。

修正后的代码

import uuid from "react-uuid";

// 给图片添加唯一标识,避免依赖Blob引用判断
interface ImageItem {
  id: string;
  blob: Blob;
}

const [images, setImages] = useState<ImageItem[]>([]);
const [selectedImageId, setSelectedImageId] = useState<string | null>(null);

// 上传图片时,为每个图片生成唯一id
const handleImageUpload = (newBlobs: Blob[]) => {
  const newImages = newBlobs.map(blob => ({
    id: uuid(),
    blob
  }));
  setImages(prev => [...prev, ...newImages]);
};

const deleteImage = (targetId: string) => {
  const filteredList = images.filter(img => img.id !== targetId);
  // 如果删除的是当前选中的图片,清空选中状态
  if (selectedImageId === targetId) {
    setSelectedImageId(null);
  }
  setImages(filteredList);
};

const toggleSelectImage = useCallback((imageId: string) => {
  setSelectedImageId(prev => prev === imageId ? null : imageId);
}, []);

return (
  {images.length > 0 &&
    images.map((img) => (
      <div
        className={`w-full h-[300px] relative ${selectedImageId === img.id ? 'border-red-500 border-4' : ''}`}
        key={img.id}
        onClick={() => toggleSelectImage(img.id)}
      >
        {/* 图片内容 */}
        <button onClick={(e) => {
          e.stopPropagation(); // 阻止触发选中事件
          deleteImage(img.id);
        }}>删除</button>
      </div>
    ))
  }
);

关键说明

  • 用id而非Blob引用做选中判断,避免Blob引用变化导致的匹配失败
  • 稳定的img.id作为key,确保React能正确追踪组件状态
  • 删除时主动处理选中状态,避免残留无效的选中标识

内容的提问来源于stack exchange,提问作者Captai-N

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 02:52:48