即使 .map 循环通过数组的所有索引,也无法在我的 React 应用程序中的 array.map 中显示我的 JSX 中的图像

Posted

技术标签:

【中文标题】即使 .map 循环通过数组的所有索引,也无法在我的 React 应用程序中的 array.map 中显示我的 JSX 中的图像【英文标题】:Cannot display images in my JSX from my array.map in my react app even though .map loops though all index of array 【发布时间】:2021-03-18 13:31:54 【问题描述】:

问题:为什么 react 不在 JSX 中显示我的图像s?我怎样才能让它显示图像s

编辑:我怀疑的问题不在于我获取数据的方式,而是我尝试显示/渲染图像的方式,我已在下面的主要问题下标记。

我有一个功能组件,它有一个 useEffect 从 firebase 获取 JSON 对象。

useEffect(()=>
        axios
        .get("http://localhost:9998/api/v1/fault/" + lastURLSegment)
        .then((response) => 
            setDisplay(response.data)
        )
    ,[])

然后我提取 imageURL 值并查询 firebase 以返回一个可在网络上查看的 url 例如https://firebasestorage.googleapis.com/v0/b/$results.bucket/o/$encodeURIComponent(item)?alt=media

一旦我能够获取图像的 URL,我将 setState 放入一个名为 objUrl 的数组中

编辑:有objOfUrl和objUrl,objOfUrl是一个var [],objOfUrl是一个状态

useEffect(()=>
        // displayspecificCases.imgURL = "fault/asd.jpg" 
        let foo = displayspecificCases.imageurl // "fault/asdfsdf.jpg,fault/1234.jpg..."
        if (foo !== undefined)
            console.log(foo) //console logs 2 images in string saperated by comma
            let bar = foo.split(','); // bar is now an array ['fault/asdfsdf.jpg','fault/1234.jpg']
            let i = 0;
            bar.map((item)=>
                console.log(item)
                if(item !== "")
                    firebase.storage().ref()
                    .child(item) 
                    .getMetadata()
                    .then((results) => 
                        objOfUrl[i] = `https://firebasestorage.googleapis.com/v0/b/$results.bucket/o/$encodeURIComponent(item)?alt=media`
                        i++ // i ++ for objOfUrl
                        console.log("i is :" + i)
                        trysetObjUrl(objOfUrl)catch(e)console.log("err is in view useEffect try catch e : " + e)
                    )
                    .catch((err) => 
                    console.log(err);
                    );
                    console.log(objOfUrl); //console logs [0: "url.....", 1: "url....."]
                
            )
        

    ,[displayspecificCases])

主要问题在这里! 所以我想在 JSX 中显示图像。所以我将数组设置为一个状态并尝试使用 .map 来返回数组中的每个项目,这样我就可以使用 img 标签来显示它们

// inside the JSX
objUrl.map((item, i) =>  console.log(i); return <div class="column"> <img key=i   src=item /> </div>)

但现在的问题是只显示 1 张图像而不是整个数组。此外,无论何时渲染,它似乎都会随机显示数组内的一个图像。如何显示数组内的所有图像?非常感谢!

旁注:我知道我的代码很乱,我还在学习中,请就如何改进某些部分提供建议和技巧!

【问题讨论】:

什么是objOfUrl?它在哪里声明/定义?我的直觉是你正在改变你的状态对象,并且没有根据objOfUrl[i] = '.......'setObjUrl(objOfUrl) 行正确更新状态。 为什么不试试 Display.map 而不是 objUrl.map?不是图片所在的位置吗? @DrewReese objOfUrl 是一个用其他常量声明的数组 var。我将编辑我的问题以包含它。关于状态对象的突变,当我做一个控制台日志时,它显示了两个图像 URL,希望能解决问题。我现在的问题是 jsx 没有渲染 objUrl 中的任何内容 请记住,在 Firebase 存储上,您需要获取“downloadUrl”firebase.google.com/docs/storage/web/download-files 以便显示它 @CyrusZei 我可以显示 1 张图片,但数组中有 2 个 url,所以应该显示 2,但只有 1 个 【参考方案1】:

如果我正确理解了您的代码,它正在执行的操作:

    displayspecificCases更新触发的效果回调 将displayspecificCases.imageurl 拆分为网址数组 为图像所在的存储桶调用 firebase 后端以获得真实图像 URL

问题

    你正在改变你的 objOfUrl 状态对象。

    objOfUrl[i] = `https://firebasestorage.googleapis.com/v0/b/$results.bucket/o/$encodeURIComponent(item)?alt=media`
    

    您将标准状态更新排入一个循环中。这会使用上一个渲染周期中的状态值将所有状态更新排入队列(记住状态是const)。这也是一个问题,因为objOfUrl IS 是状态引用。它应该是一个新的数组引用。

    setObjUrl(objOfUrl)
    

    我想这不是您的问题的原因,但使用 array.prototype.map 发出数组副作用是不正确的。

解决方案

使用功能状态更新来

    在循环中正确地将状态更新排入队列 正确返回新的状态数组引用

代码

useEffect(() => 
  if (displayspecificCases.imageurl) 
    displayspecificCases.imageurl.split(",").forEach((item, i) => 
      console.log(item);
      if (item !== "") 
        firebase
          .storage()
          .ref()
          .child(item)
          .getMetadata()
          .then((results) => 
            // Construct complete image URL
            const url = `https://firebasestorage.googleapis.com/v0/b/$
              results.bucket
            /o/$encodeURIComponent(item)?alt=media`;

            console.log("i is :" + i);
            try 
              // Update state array at index i
              setObjUrl((objOfUrl) =>
                objOfUrl.map((objUrl, index) => (index === i ? url : objUrl))
              );
             catch (e) 
              console.log("err is in view useEffect try catch e : " + e);
            
          )
          .catch((err) => 
            console.log(err);
          );
      
    );
  
, [displayspecificCases]);

// Log state when it updates
useEffect(() => 
  console.log(objOfUrl); //console logs [0: "url.....", 1: "url....."]
, [objOfUrl]);

【讨论】:

感谢您的解决方案,不幸的是,要么我在某个地方搞砸了,要么问题不在于您提供的解决方案。实现代码后,我仍然遇到同样的问题,即页面仅显示 1 张图像。我强烈怀疑问题在于 JSX 以及我如何尝试渲染图像。但对于我的生活,我似乎无法找到另一种方式来渲染它。 另外,另一个问题,在 //Update state array at index i 下。我不完全理解 try-catch 块试图实现什么,在匿名函数中,参数 objOfUrl 是空的,那么 .map 将如何与之交互? @daph99 您能否尝试创建一个 running 代码框来重现该问题并将其链接到您的问题中(并在此处 ping @我)?对于第二个问题,objOfUrl 是一个数组,所以当您循环分割图像 urls 数组时,您正在构建这个状态数组。该地图是必要的,因为当firebase调用解析时无法保证顺序,因此您需要索引来匹配元素。我也不太明白为什么在状态更新时会有一个 try/catch,但是你原来的 sn-p 有它,所以我认为它在那里是有原因的。 我认为你是对的,但我太笨了,无法理解,直到有人坐下来向我解释。非常感谢您的帮助!【参考方案2】:

已解决

解决方案说明如下

 useEffect(()=>
        axios
        .get("http://localhost:9998/api/v1/fault/" + lastURLSegment)
        .then(async (response) => 
            setDisplay(response.data)
            const imagesToConstruct = await response.data.imageurl.slice(0,-1).split(",")
            // console.log(imagesToConstruct)
            imagesToConstruct.length > 0 && imagesToConstruct.forEach((item, i) => 
                if (item !== "") 
                firebase
                    .storage()
                    .ref()
                    .child(item)
                    .getMetadata()
                    .then((results) =>  //main solution here
                        setImages((prevImages) => [...prevImages, `https://firebasestorage.googleapis.com/v0/b/$results.bucket/o/$encodeURIComponent(item)?alt=media`])
                    ).catch((err) => 
                        console.log(err);
                    );
                
            )            
        )
    , [])

问题

每次调用 useEffect 时,构造的 url 都会被解析成一个临时数组 (objOfUrl) 使用 setobjUrl(objOfUrl) setState 到 objUrl 但是,由于某种原因,我无法弄清楚为什么它会覆盖状态并且状态仅以一个构造的 URL 结束。所以我不得不咨询某人来帮助我编写代码,这就是他提供的解决方案。

解决方案说明 将 2 个 useEffect 压缩为 1,然后使用扩展运算符设置新状态 (images)

感谢那些试图提供帮助并回复此帖子的人!

【讨论】:

以上是关于即使 .map 循环通过数组的所有索引,也无法在我的 React 应用程序中的 array.map 中显示我的 JSX 中的图像的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:即使 userData 是数组,userData.map 也不是函数

JavaScript的map循环forEach循环filter循环

CLion无法解析类型std :: unordered_map,即使它提示我包含标题和编译工作

go语言学习---map集合

即使 UV-Mapping 非常适合,Blender 纹理在反复烘烤后也无法正确显示

使用map方法Javascript遍历数组中的所有数组索引