Next.js应用上传文本/图片触发运行时错误求助
问题:发布带图片的帖子时数据库存入成功但触发运行时错误
我参照在线教程开发了支持用户发布内容并可选上传图片的功能,前端采用Next.js,数据库使用Firestore。点击提交按钮时,帖子可成功存入数据库,但会触发运行时错误,界面及控制台均报错。在uploadString前执行console.log(selectedFile),结果显示selectedFile为null。
相关代码如下:
/* eslint-disable @next/next/no-img-element */ import { EmojiHappyIcon, PhotographIcon } from '@heroicons/react/outline'; import { addDoc, collection, serverTimestamp, updateDoc, } from 'firebase/firestore'; import { getDownloadURL, ref, uploadString } from 'firebase/storage'; import { useSession, signOut } from 'next-auth/react'; import { useRef, useState } from 'react'; import { db, storage } from '../firebase'; export default function Input() { const { data: session } = useSession(); const [input, setInput] = useState(''); const [selectedFile, setSelectedFile] = useState(null); const filePickerRef = useRef(null); const sendPost = async () => { const docRef = await addDoc(collection(db, 'posts'), { id: session.user.uid, text: input, userImg: session.user.image, timestamp: serverTimestamp(), name: session.user.name, username: session.user.username, }); const imageRef = ref(storage, `posts/${docRef.id}/image`); if (setSelectedFile) { await uploadString(imageRef, selectedFile, 'data_url').then(async () => { const downloadURL = await getDownloadURL(imageRef); await updateDoc(doc(db, 'posts', docRef.id), { image: downloadURL, }); }); } setInput(''); }; const addImageToPost = (e) => { const reader = new FileReader(); if (e.target.files[0]) { reader.readAsDataURL(e.target.files[0]); } reader.onload = (readerEvent) => { setSelectedFile(readerEvent.target.result); }; }; return ( <> {session && ( <div className="flex border-b border-gray-200 p-3 space-x-3"> <img onClick={signOut} src={session?.user?.image} alt="user-img" className="h-11 w-11 rounded-full cursor-pointer hover:brightness-95" /> <div className="w-full divide-y divide-gray-200"> <div className=""> <textarea className="w-full border-none focus:ring-0 text-lg placeholder-gray-700 tracking-wide min-h-[50px] text-gray-700 font-['Quattrocento']" rows="2" placeholder="Share a news article you want others to comment on!" value={input} onChange={(e) => setInput(e.target.value)} ></textarea> </div> <div className="flex items-center justify-between pt-2.5"> <div className="flex"> <div onClick={() => filePickerRef.current.click()}> <PhotographIcon className="h-10 w-10 hoverEffect p-2 text-gray-500 hover:bg-gray-100 " /> <input type="file" hidden ref={filePickerRef} onClick={addImageToPost} /> </div> <EmojiHappyIcon className="h-10 w-10 hoverEffect p-2 text-gray-500 hover:bg-gray-100" /> </div> <button onClick={sendPost} disabled={!input.trim()} className="bg-gray-500 text-white px-4 py-1.5 rounded font-bold shadow-md hover:brightness-95 disabled:opacity-50 font-['Quattrocento']" > Comment </button> </div> </div> </div> )} </> ); }
错误排查及解决建议
错误根源
代码中的if (setSelectedFile)判断逻辑完全错误:setSelectedFile是React的state更新函数,永远为真值,这导致即使用户没有选择图片(selectedFile为null),也会执行uploadString操作,而Firebase的uploadString无法接受null作为数据源,从而触发运行时错误。
修复步骤
修正上传判断条件
将if (setSelectedFile)改为if (selectedFile),仅当用户确实选择了图片时才执行上传逻辑:if (selectedFile) { await uploadString(imageRef, selectedFile, 'data_url').then(async () => { const downloadURL = await getDownloadURL(imageRef); await updateDoc(doc(db, 'posts', docRef.id), { image: downloadURL, }); }); }重置图片选择状态
上传完成后重置selectedFile为null,避免下次发布时重复上传之前的图片:if (selectedFile) { // 上传逻辑... setSelectedFile(null); }修复文件选择事件绑定
文件选择器的onClick事件改为onChange,避免用户打开文件选择框但取消选择时,addImageToPost被错误触发:<input type="file" hidden ref={filePickerRef} onChange={addImageToPost} />
内容的提问来源于stack exchange,提问作者user18792970
相关产品推荐
相关产品推荐

