如何动态地将图像元素添加到我的页面?

How can I add image elements to my page dynamically?

我的 React 应用已连接到 Firebase Firestore 和 Storage,但我无法从 Storage 读取文件并显示它们。

有一次,我有以下数据数组:

metricData = [

  "2021-07-15" = { id1: "/image1url", id2: "/image2url", ... },
  "2021-07-14" = { id2: "/image2url", ... },
  ...

]

其中 'id1' 等是各种指标的 firebase ID,每个指标的值(例如“/image1.url”)是存储在我的 Firebase 存储中的图像的路径。

然后我有一个我想查看的 ID 数组:

metricIds = [ id1, id2, ..., idx ]

所以,我想遍历 metricIds,对于其中的每个 id,我想查看今天 (2021-07-15) 的 metricData 中的记录,并获取与那个身份证。然后我想读入关联的图像,并显示它。

我在渲染图像时遇到了问题,因为当我从 Firebase 获取它们时,React 已经继续前进并且不会渲染它们。

到目前为止,我有以下内容(为了清楚起见,我删除了所有错误检查):

const MetricImages = (metricIds, metricData) => {

  const firebase = useContext(FirebaseContext)
  const today = new Date()

  return (
    <>
      {
        metricIds.map((metricId) => {
          // Get image url
          const url = metricData[moment(today).format('YYYY-MM-DD')][metricId]
          // Now get image at that url from Firebase storage
          firebase
          .doGetFile(url)
          .then((resImage:string) => {
            // resImage should now contain the relevant image, so we want to display it
          })
        })
      }
    </>
            

export default MetricImages

问题是,地图语句的 return 和图像元素 return 放在哪里?我想 return 类似

<img key={metricId} src={resImage} />

对于每个 metricId,因此最终组件应该生成如下元素:

  <>
   <img key='id1' src='image1src' />
   <img key='id2' src='image2src' />
   ... more images ...
  </>

如果我在 'then' 语句中执行 return,React 会继续执行并且永远不会接收它。我尝试用 await 调用 firebase.doGetFile() (将映射函数更改为异步),但仍然没有任何结果。

如果我把 return 放在 'then' 之后,那时候我没有 src 值,所以我只是 return <img key='id1' src='' /> 显然没有没用。

接下来我可以尝试什么?

您应该将它们存储到 useState 中,然后在功能组件中 useEffect 的组件加载周期中获取您的数据,然后当 Firebase 在 then 中提供您的图像时,设置它们放入您将与 useState 一起保存的变量中。我不熟悉 Firebase 流程,但你应该这样做:

const MetricImages = (metricIds, metricData) => {
   const [images, setImages] = useState([]);

   useEffect(() => {
      // Your data fetch methods will be here
      const url = metricData[moment(today).format('YYYY-MM-DD')][metricId]
      firebase
          .doGetFile(url)
          .then((resImage) => {
            setImages(resImage)
          })
   }, [])


   return <>
    {images.length > 0 ?
      {images.map(image =>
         <img src={image.src} ... />
      )}
    : <>loading..</>}
   </>
}