我有一个MERN社交媒体应用程序,允许用户上传个人资料和封面图片在他们的个人资料页面.一切正常,但当用户上传图片时,显示的封面图片应该设置为刚刚上传的图片.我从教程中得到了这段代码,它工作得很好,但我必须刷新页面才能显示新图像.我注释掉了setError(error.Response.data.error)行和控制台.记录了错误并得到如下结果:
TypeError: Cannot set properties of null (setting 'src')
at updateCoverPicture (Cover.js:103:1)
第103行在updateCoverPicture函数中,它是:
coverRef.current.src = res[0].url;
而我试图引用的形象是:
{cover && !coverPicture && (
<img src={cover} className="cover" alt="" ref={coverRef} />
)}
其 idea 是,如果我没有在上传新的图像,将显示当前的封面图像,但如果有封面图片(正在上传的那个),它将显示在那里.当该函数运行时,上传的图像带有保存到数据库中的用户记录的Cloudinary url,并创建一个POST,然后将overPIcture设置为"",然后运行上面的代码行以显示新上传的图像.
一切正常,除非我收到该错误,而不是正在显示的图像.
如果我从第{cover&;&;!cover Picture&;&;行中删除!overPicture&;&;(它可以工作,但当前图像被下推,并且我试图上传的图像显示在其上方.一旦我保存了封面图片,图像就会消失,图像也会更新,但它们都在那里看起来不太好.
以下是整个页面:
import { useCallback, useEffect, useRef, useState } from 'react';
import Cropper from 'react-easy-crop';
import getCroppedImg from '../../helpers/getCroppedImg';
import { uploadImages } from '../../functions/uploadImages';
import { updateCover } from '../../functions/user';
import { createPost } from '../../functions/post';
import PulseLoader from 'react-spinners/PulseLoader';
const Cover = ({ cover, visitor, user }) => {
const [showCoverMenu, setShowCoverMenu] = useState(false);
const [coverPicture, setCoverPicture] = useState('');
const [loading, setLoading] = useState('');
const [error, setError] = useState('');
const [crop, setCrop] = useState({ x: 0, y: 0 });
const [zoom, setZoom] = useState(1);
const [croppedAreaPixels, seetCroppedAreaPixels] = useState(null);
const [width, setWidth] = useState();
const refInput = useRef(null);
const menuRef = useRef(null);
const coverWidthRef = useRef(null);
const coverRef = useRef(null);
const onCropComplete = useCallback(
(croppedArea, croppedAreaPixels, picModalOpen) => {
seetCroppedAreaPixels(croppedAreaPixels);
},
[]
);
const handleImage = (e) => {
let file = e.target.files[0];
if (
file.type !== 'image/jpeg' &&
file.type !== 'image/jpg' &&
file.type !== 'image/png' &&
file.type !== 'image/webp' &&
file.type !== 'image/gif'
) {
setError(`${file.name} format is not supported.`);
return;
} else if (file.size > 1024 * 1024 * 5) {
setError(`${file.name} is too large max 5mb allowed.`);
return;
}
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (event) => {
setCoverPicture(event.target.result);
};
};
const getCroppedImage = useCallback(
async (show) => {
try {
const img = await getCroppedImg(coverPicture, croppedAreaPixels);
if (show) {
setZoom(1);
setCrop({ x: 0, y: 0 });
setCoverPicture(img);
} else {
return img;
}
} catch (error) {
console.log(error);
}
},
[croppedAreaPixels, coverPicture, setCoverPicture]
);
useEffect(() => {
setWidth(coverWidthRef.current.clientWidth);
}, [window.innerWidth]);
const updateCoverPicture = async () => {
try {
setLoading(true);
let img = await getCroppedImage();
let blob = await fetch(img).then((b) => b.blob());
const path = `tyt/${user.user.username}/cover_pictures`;
let formData = new FormData();
formData.append('file', blob);
formData.append('path', path);
const res = await uploadImages(formData, path, user.token);
const updated_Picture = await updateCover(
res[0].url,
user.user._id,
user.token
);
if (updated_Picture === 'ok') {
const new_post = await createPost(
'cover',
null,
res,
user.user._id,
user.token
);
if (new_post === 'ok') {
setLoading(false);
setCoverPicture('');
coverRef.current.src = res[0].url;
} else {
setLoading(false);
setError(new_post);
}
} else {
setLoading(false);
setError(updated_Picture);
}
} catch (error) {
setLoading(false);
//setError(error.response.data.error);
console.log(error);
}
};
return (
<div className="profile_cover" ref={coverWidthRef}>
{coverPicture && (
<div className="save_changes_cover">
<div className="save_changes_left">
<i className="public_icon"></i>
Your cover photo is public
</div>
<div className="save_changes_right">
<button
className="blue_btn opacity_btn"
onClick={() => setCoverPicture('')}
>
Cancel
</button>
<button className="blue_btn" onClick={() => updateCoverPicture()}>
{loading ? <PulseLoader color="#fff" size={5} /> : 'Save Changes'}
</button>
</div>
</div>
)}
<input
type="file"
ref={refInput}
hidden
accept="image/jpg,image/jpeg,image/png,image/webp,image/gif"
onChange={handleImage}
/>
{error && (
<div className="postError comment_error">
<div className="postError_error">{error}</div>
<button className="blue_btn" onClick={() => setError('')}>
Try again
</button>
</div>
)}
{coverPicture && (
<div className="cover_cropper">
<Cropper
image={coverPicture}
crop={crop}
zoom={zoom}
aspect={width / 350}
onCropChange={setCrop}
onCropComplete={onCropComplete}
onZoomChange={setZoom}
showGrid={true}
objectFit="horizontal-cover"
/>
</div>
)}
{cover && !coverPicture && (
<img src={cover} className="cover" alt="" ref={coverRef} />
)}
{!visitor && (
<div className="update_cover_wrapper">
<div
className="open_cover_update"
onClick={() => setShowCoverMenu((prev) => !prev)}
>
<i className="camera_filled_icon"></i>
Add cover photo
</div>
{showCoverMenu && (
<div className="open_cover_menu" ref={menuRef}>
<div className="open_cover_menu_item hover1">
<i className="photo_icon"></i>
Select Photo
</div>
<div
className="open_cover_menu_item hover1"
onClick={() => refInput.current.click()}
>
<i className="upload_icon"></i>
Upload Photo
</div>
</div>
)}
</div>
)}
</div>
);
};
export default Cover;