在 JSX 中映射多个数组
Mapping multiple arrays in JSX
我试图在映射到 JSX 中的数组时以某种方式显示一些 html 元素。我希望它像:
标题
Link
标题
Link
但是当我尝试时,我总是以这样的方式结束:
标题
标题
Link
Link
这就是数组的结构。
在我的代码中,这就是我映射数组的方式。
{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 的同时迭代到下一个文件名。它应该与每个地图迭代中的 filename
和 url
成对出现。我希望这是有道理的。
完整代码:
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
不是嵌套两个地图,而是将它们设置为状态,然后使用其中一个状态循环,这假设每个文件名在与其关联的同一索引处都有一个 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>
)
})
}
res.items
是由 rootRef.listAll()
返回的 References 的数组,当您设置为 filename
时,您无法神奇地拉出 name
属性这样{item.filename[0].name}
考虑重构您的 fileNames
函数以解析对象数组,其中 filename
键设置为每个 item
的 name
。
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>
您可以使用地图索引代替直接访问索引。
在这里,我根据您的 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>
);
}
要解决这个问题,您可以在设置 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>
我试图在映射到 JSX 中的数组时以某种方式显示一些 html 元素。我希望它像:
标题
Link
标题
Link
但是当我尝试时,我总是以这样的方式结束:
标题
标题
Link
Link
这就是数组的结构。
在我的代码中,这就是我映射数组的方式。
{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 的同时迭代到下一个文件名。它应该与每个地图迭代中的 filename
和 url
成对出现。我希望这是有道理的。
完整代码:
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
不是嵌套两个地图,而是将它们设置为状态,然后使用其中一个状态循环,这假设每个文件名在与其关联的同一索引处都有一个 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>
)
})
}
res.items
是由 rootRef.listAll()
返回的 References 的数组,当您设置为 filename
时,您无法神奇地拉出 name
属性这样{item.filename[0].name}
考虑重构您的 fileNames
函数以解析对象数组,其中 filename
键设置为每个 item
的 name
。
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>
您可以使用地图索引代替直接访问索引。 在这里,我根据您的 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>
);
}
要解决这个问题,您可以在设置 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>