我有一个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&amp;&amp;!cover Picture&amp;&amp;行中删除!overPicture&amp;&amp;(它可以工作,但当前图像被下推,并且我试图上传的图像显示在其上方.一旦我保存了封面图片,图像就会消失,图像也会更新,但它们都在那里看起来不太好.

以下是整个页面:

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;

推荐答案

经过几天的寻找,我把这个问题贴了出来,当然一天后就找到了解决方案.答案来自这个问题How 至 use Refs 至 change image src in React js的答案.

我没有使用useRef来重置封面图像,而是使用了useEffect和useState. 我使用useState将封面设置为存在的导入封面:

const [image, setImage] = useState(cover ? cover : '');

然后我就变了

cRef.current.src = res[0].url;

setImage(res[0].url);

Then added a useEffect 至 set the image 至 the newly uploaded image

useEffect(() => {
    if (loading) {
      setTimeout(() => {
        if (loading) {
          setLoading(false);
          setImage(cover);
        }
      }, 100);
    }
  }, [loading, setLoading, setImage, cover]);

然后我改变了:

<img src={cover} className="cover" alt="" ref={coverRef} />

<img src={image} className="cover" alt="" ref={coverRef} />

Reactjs相关问答推荐

CreateBrowserRouter将props 传递给父组件以验证权限

为什么安装FLOBIT后,所有的输入FIELD现在都有一个蓝色的轮廓?

Formik验证不适用于物料UI自动完成

有没有办法在Shopify中显示自定义计算的交货日期?

为什么我的react虚拟化列表不显示滚动条,除非我确保高度低于rowCount*rowHeight?

react 挂钩-使用有效澄清

左边框不在图表中显示

在transformResponse中使用来自其他查询的缓存

在Reaction中的第一次装载时,Use Effect返回空数组

当 URL 与我声明的任何路由都不匹配时,如何使用不会重定向到错误页面的动态 URL? - react 路由 dom

Yup.number().integer() 不将 1.0 视为小数,如何解决这个问题?

未捕获的运行时错误:对象作为 React 子项无效

未处理的拒绝 (TypeError):无法读取未定义的属性(读取协议)

无法读取未定义的属性(读取值)...TypeError:无法读取未定义的属性(读取值)

Recharts 笛卡尔网格 - 垂直线和水平线的不同样式

vdom 最终更新了 dom(在比较之后)任何 dom 更改实际上应该触发整个树的重绘和回流,那么 vdom 有什么用?

使用 react-router-dom 时弹出空白页面

如何在 Cypress E2E 的站点上测试react 组件?

如何在 react-router-dom v6 中实现监听功能?

我想将悬停 colored颜色 更改为红色.写了一个话题,这个元素没有react ,怎么解决呢?