【问题标题】:Mapping multiple arrays in JSX在 JSX 中映射多个数组
【发布时间】:2021-07-09 03:51:01
【问题描述】:

在 JSX 中映射数组时,我试图以某种方式显示一些 html 元素。我希望它是这样的:

标题
链接

标题
链接

但是当我尝试时,我总是以这样的方式结束它:

标题
标题

链接
链接

这就是数组的结构。

在我的代码中,这就是我映射数组的方式。

{audioInfo.map((item, index) => {
                   
   return ( <div key={index}>

                        
     <div>{item.filename[0].name}</div>
                            
         {

          item.url.map((u,i)=>(
              <div key={i}>
                                
                 <audio controls src={u}> </audio>
              </div>
           ))
         }
  </div> )
 })}

这是我遇到问题的部分。

item.filename[0].name

这只会获取第一个文件名,但我不确定如何迭代到下一个文件名,同时仍然像我想要的那样呈现 html。在每次映射迭代中,它应该与filenameurl 成对出现。我希望这是有道理的。

完整代码:

import React, { useState, useEffect, useRef } from 'react';
import firebase from "firebase/app";
import storage from "firebase/storage";
import  firebaseConfig from "../dropzone/config";

import {
    BrowserRouter as Router,
    Switch,
    Route,
    Link,
    useRouteMatch,
    BrowserRouter,
    useParams
  } from "react-router-dom";
import { isElement } from 'react-dom/test-utils';


if (!firebase.apps.length) {
    firebase.initializeApp(firebaseConfig);

}else {
    firebase.app(); // if already initialized, use that one
}

  // router is getting the current path name


const FolderPage = () => {

    let {folder} = useParams();

    let fb_storage = firebase.storage();
    let storageRef = fb_storage.ref();  
    
    let rootRef = storageRef.child(folder);


    const [files, setFiles] = useState([]); 
   
    const [audioInfo, setAudioInfo] = useState([]);    

        
    const fileNames =  () =>{
        let temp = [];
        rootRef.listAll().then( function(res) {
            
            let promises = res.items.map(item => item.getDownloadURL());

            Promise.all(promises).then((downloadURLs)=>{
                        
                  
                    setAudioInfo([
                        {
                            filename:res.items, 
                            url: downloadURLs 
                        }  
                    ])
                })
          
            }).catch(function(error) {
           
        });
            
    
    }

    useEffect(()=>{
        fileNames();
    },[])


    console.log(audioInfo)
    

    return (
        <>
            <div>hello {folder}</div>
          

            <div>

                
                {audioInfo.map((item, index) => {
                   
                   return ( <div key={index}>

       
                           <div>{item.filename[0].name}</div>
                            
                            {

                            item.url.map((u,i)=>(
                               <div key={i}>
                                <span>{u.name}</span>   
                                <audio controls src={u}> </audio>
                               </div>
                            ))
                            }

                           
                    </div> )
                    })}
                
            </div>

        </>
    )
}

export default FolderPage

【问题讨论】:

  • res.items 是一堆未解决的承诺。为什么将文件名设置为res.items

标签: javascript reactjs firebase iteration jsx


【解决方案1】:

要解决这个问题,您可以在设置 audioInfo 状态之前创建一个变量。

const files = []
res.items.map((item, i)=>{
  files.push({url: downloadURLs[i], file: item.name })     
})
setAudioInfo(files)

现在您可以简单地迭代和渲染

<div>                
     {audioInfo.map((item, index) => {                   
       return ( <div key={index}>                           
        <span>{item.file}</span>   
        <audio controls src={item.url}> </audio>                                                        
        </div> )
       })}                
</div>

【讨论】:

  • 多么传奇!像魅力一样工作。谢谢
【解决方案2】:

不是嵌套两个映射,而是将它们设置为状态,然后使用其中一个状态循环,这假设每个文件名在与其关联的同一索引处都有一个 url。

const [names, setNames] = useState([])
const [urls, setURL] = useState([])

useEffect(() => {
    audioInfo[0].filename.forEach((i) => setNames([...names, i.name]))
    audioInfo[0].url.forEach((i) => setURL([...urls, i]))
}, [])

{
    names.map((item, index) => {
        return (
            <div key={index}>
                <div>{item}</div>
                <div key={index}>
                    <audio controls src={urls[index]} />
                </div>
            </div>
        )
    })
}

【讨论】:

    【解决方案3】:

    res.itemsReferences 返回的References 数组,当您设置为filename 时,您不能像{item.filename[0].name} 这样神奇地拉取name 属性

    考虑重构您的fileNames 函数以解析为一个对象数组,其中filename 键设置为每个itemname

    const fileNames = () => {
      let temp = [];
      rootRef
        .listAll()
        .then(function (res) {
    
          let promises = res.items.map((item) =>
            item.getDownloadURL().then((downloadURLs) =>
              Promise.resolve([
                {
                  filename: item.name,
                  url: downloadURLs,
                },
              ]));
          );
    
          Promise.all(promises).then((audioInfo) => {
            setAudioInfo(audioInfo);
          });
        })
        .catch(function (error) {});
    };
    

    现在在您的 JSX 中,您可以简单地引用 filename

    <div>{item.filename}</div>
    

    【讨论】:

      【解决方案4】:

      您可以使用地图索引,而不是直接访问索引。 在这里,我根据您的 json 声明了虚拟 json 列表并按照您的要求呈现输出

      export default function App() {
        const list = [
          {
            file: ["ABC", "CDE"],
            url: ["link1", "link2"]
          },
          {
            file: ["ABC2", "CDE2"],
            url: ["link12", "link22"]
          }
        ];
        return (
          <div className="App">
            <h1>List Map</h1>
            {list.map((item, index) => {
              return (
                <>
                  {item.file.map((file, pos) => {
                    return (
                      <>
                        <p>file : {file}</p>
                        <p>Url : {item.url[pos]}</p>
                        <hr/>
                      </>
                    );
                  })}
                </>
              );
            })}
          </div>
        );
      }
      

      【讨论】:

        猜你喜欢
        • 2019-03-27
        • 2020-09-25
        • 2019-08-16
        • 2020-07-13
        • 2020-07-29
        • 2021-09-04
        • 1970-01-01
        • 2021-03-10
        • 2019-12-08
        相关资源
        最近更新 更多