尝试访问 S3 时呈现比上一次呈现更多的挂钩

Rendered more hooks than during the previous render when trying to access S3

我正在做一个带有 React 的小应用程序,我将图片放在私有 S3 存储桶中,只有注册用户才能访问它。我在网页设计方面一点经验都没有(我更像是一名数据科学家),所以我遵循的策略可能不是最有效的策略。 但是,我使用 Cognito 进行了注册和登录,它运行正常。在身份池中,我将读取角色放入桶中。现在我正在尝试在该存储桶中渲染示例图片。

这是我现在拥有的代码:

import React, { useState } from "react";
import { Storage } from "aws-amplify";

export default function LoadImage(props){
  const [imgUrl, setImgUrl] = useState("");

  async function onLoad(){
    try{
      const url = await Storage.get(props);
      setImgUrl(url);
    }
    catch(e){
      alert(e);
    }
  }

  onLoad();
  return(
    <img src={imgUrl} />
  );
}

以及它打算在 App.js 中使用它作为

<div>{isAuthenticated ? LoadImage("img/images.png") : <>"No pic 4 u"</>}</div>

此代码给出错误 Rendered more hooks than during the previous render.。请耐心等待,我不知道钩子是什么,因为我正在从互联网上挑选代码示例。我试着把它直接放在<img>标签中作为

<div>{isAuthenticated ? <img src={Storage.get("img/images.png")} /> : <>"No pic 4 u"</>}</div>

但是当我检查 html 时,它显示为

<div>{isAuthenticated ? <img src=[Object Promise] /> : <>"No pic 4 u"</>}</div>

同样,我对 promises 知之甚少(来自 react 文档)。如果我输入 alert(Storage.get("img/images.png")) 它会打印出正确的 url.

我认为您绝对应该先阅读一些文档并熟悉基础知识。 不管怎样,你应该怎么做:

export default function LoadImage({link}){
  const [imgUrl, setImgUrl] = useState("");

  async function onLoad(){
    try{
      const url = await Storage.get(link);
      setImgUrl(url);
    }
    catch(e){
      alert(e);
    }
  }
  useEffect(onLoad, []);
  return(
    <img src={imgUrl} />
  );
}

并这样称呼它:

<div>{isAuthenticated ? <LoadImage link="img/images.png"/> : <>"No pic 4 u"</>}</div>

它可能看起来像这样:

export default function useLoadImage(url, isAuthenticated) {
  const [imgUrl, setImgUrl] = useState(
    isAuthenticated ? '' : <>"No pic 4 u"</>
  );
  useEffect(() => {
    async function onLoad() {
      try {
        const iUrl = await Storage.get(url);
        //should check if component is still mounted before trying to set state
        //https://github.com/jmlweb/isMounted
        setImgUrl(iUrl);
      } catch (e) {
        alert(e);
      }
    }
    isAuthenticated && onLoad(); //only call if is authenticated
  }, [url, isAuthenticated]); //only do again if url or is authenticated changes
  return <img src={imgUrl} />;
}
//using the custom hook
const img = useLoadImage('url', isAuthenticated);

您不应为每个组件多次使用此挂钩。如果您确实需要多张图片,您可以将其包装在一个组件中:

function AmazonImage = ({url,isAuthenticated}){
  return useLoadImage(url,isAuthenticated)
}
//using the wrapper
<AmazonImage url='url' isAuthenticated={isAuthenticated} />