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

Cloudinary图片重复上传求助:React组件调用时上传两次

问题分析与解决方案

问题根源

你的代码出现重复上传的核心原因有两点:

  1. React 18 Strict Mode 特性:开发环境下,Strict Mode 会强制重复执行 useEffect 以检测副作用,导致上传逻辑被触发两次。
  2. 依赖项与状态设计缺陷:原 useEffect 依赖了 isLoading,当调用 setIsLoading(false) 时会再次触发钩子;同时组件内部的 imageUploaded 状态在组件重新渲染时会被重置,可能导致重复执行上传逻辑。

修复后的代码

'use client';
import React, { useEffect, useState, useRef } from 'react';
import { LoadingLine } from './Loading';

export default function SnapImages({ snap, setSnap }) {
    const [isLoading, setIsLoading] = useState(true);
    const uploadedFileRef = useRef(null); // 用ref跟踪已处理的文件,避免重复上传

    useEffect(() => {
        // 仅处理File类型的snap,且排除已上传过的文件
        if (snap instanceof File && snap !== uploadedFileRef.current) {
            const formData = new FormData();
            formData.append('file', snap);
            formData.append('upload_preset', '********');
            
            uploadedFileRef.current = snap; // 标记当前文件为已处理
            setIsLoading(true);

            fetch('https://api.cloudinary.com/v1_1/********/image/upload/', {
                method: 'POST',
                body: formData,
            })
                .then((response) => response.json())
                .then((data) => {
                    setSnap(data.secure_url);
                    console.log(data.secure_url);
                    setIsLoading(false);
                })
                .catch((error) => {
                    console.log('Error', error);
                    setIsLoading(false);
                    uploadedFileRef.current = null; // 上传失败时重置,允许重试
                });
        } else if (!(snap instanceof File)) {
            // 若snap已经是Cloudinary返回的URL,直接结束加载状态
            setIsLoading(false);
        }
    }, [snap, setSnap]);

    if (isLoading) return (<LoadingLine />);

    return (
        <>
            Thumbnail upload completed
        </>
    );
}

关键优化点

  • 用 useRef 替代状态跟踪上传状态:useRef 的值不会随组件重新渲染重置,能精准标记已处理的文件,避免重复上传。
  • 精简 useEffect 依赖项:移除不必要的 isLoading 依赖,仅保留触发上传逻辑的核心依赖 snap 和 setSnap。
  • 增加类型判断:通过 snap instanceof File 确保只有文件类型的参数才会触发上传,避免对已上传完成的URL执行无效逻辑。
  • 错误处理优化:上传失败时重置 uploadedFileRef,允许用户重新上传同一文件。

内容的提问来源于stack exchange,提问作者Jay Lee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 01:51:26