Next.js单输入框上传图/视频后预览组件判断失效问题求助
问题:图片/视频上传预览判断失效,始终显示视频组件
实现支持图片和视频上传的输入框后,上传功能正常,但预览时无论上传图片还是视频,都会触发视频组件渲染,完全不走图片分支。尝试用useState存储file_type也未解决问题。
错误原因
- 变量作用域与渲染机制冲突:组件顶部声明的
var file_type是函数级变量,React组件每次状态更新都会重新执行整个组件函数,该变量会被重置为undefined。渲染阶段判断file_type === "image"时,实际是undefined === "image",永远为false,因此始终走视频分支。 - useState用法错误(若曾尝试):若之前仅声明
useState但未在onFileChange中正确更新状态,或渲染时仍使用原变量而非state值,同样会导致判断失效。
修复方案
通过useState持久化存储文件类型,确保组件渲染时能获取到正确值,同时添加Blob URL清理逻辑避免内存泄漏。
修复后的完整代码
import React, { useState, useEffect } from 'react'; import { CgAttachment } from "react-icons/cg"; import { MdDeleteForever } from 'react-icons/md'; const ChatFooter = () => { const [attachmentPreview, setAttachmentPreview] = useState(null); const [attachment, setAttachment] = useState(null); // 新增state存储文件类型 const [fileType, setFileType] = useState(null); // 清理Blob URL,避免内存泄漏 useEffect(() => { return () => { if (attachmentPreview) { URL.revokeObjectURL(attachmentPreview); } }; }, [attachmentPreview]); const onFileChange = (e) => { const file = e.target.files[0]; if (!file) return; const file_name = file.name; let file_type = file.type.toLowerCase(); // 提取文件类型前缀(image/video) file_type = file_type.substr(0, file_type.indexOf("/")); const blobUrl = URL.createObjectURL(file); setAttachment(file); setAttachmentPreview(blobUrl); // 更新文件类型state setFileType(file_type); e.target.value = ""; } return ( <> {attachmentPreview && ( <div className='absolute w-[100px] h-[100px] bottom-16 left-0 bg-c1 p-2 rounded-md'> {/* 使用state中的fileType进行判断 */} {fileType === "image" ? ( <img src={attachmentPreview} alt='Attachment Preview' className='w-full h-full object-cover' /> ) : ( <video width="100" height="100" controls className='w-full h-full object-cover'> <source src={attachmentPreview} type={attachment?.type} /> </video> )} <div className='absolute -right-2 -top-2 cursor-pointer w-6 h-6 rounded-full bg-red-500 flex justify-center items-center' onClick={() => { setAttachment(null); setAttachmentPreview(null); setFileType(null); }} > <MdDeleteForever size={14} /> </div> </div> )} <div className='shrink-0'> <input type='file' id='fileUploader' className='hidden' onChange={onFileChange} accept='image/*, video/*' /> <label htmlFor='fileUploader'> <CgAttachment size={20} /> </label> </div> </> ); } export default ChatFooter;
关键修复点
- 新增
const [fileType, setFileType] = useState(null)持久化存储文件类型,确保渲染时能获取最新值 - 在
onFileChange中处理完文件类型后,调用setFileType(file_type)更新状态 - 渲染阶段使用
fileType代替原变量进行分支判断 - 添加
useEffect钩子清理Blob URL,避免内存泄漏 - 视频组件
type属性使用文件原生类型,提升兼容性 - 给图片和视频添加样式,确保预览内容适配容器尺寸
内容的提问来源于stack exchange,提问作者Jatin Kumar
相关产品推荐
相关产品推荐

