Why when I added await
inside for-loop
, it will throw me error? How should I fix it?
export default async function DetailsViewer({
}) {
const galleryList = [];
const metadata = []
const [data, setData] = useState()
useEffect(() => {
const getNFTDetails = async () => {
fetch("http://localhost:4000/getDetails").then(response => {
return response.json()
})
.then(posts => {
setData(posts)
})
.then((err) => {
console.log(err);
})
}
getNFTDetails()
}, []);
for (const a in data) {
metadata[a] = await fetchIPFSJSON(data[a].uri);
if (metadata[a].image) {
metadata[a].image = makeGatewayURL(metadata[a].image);
}
galleryList.push(
<Card
style={{ width: 200 }}
key={data[a].name}
title={
<div>
{data[a].name}{" "}
<a
target="_blank"
rel="noreferrer"
>
{/* <LinkOutlined /> */}
</a>
</div>
}
>
<img src={data[a].image} style={{ maxWidth: 130 }} />
</Card>,
);
}
return (
<div style={{ maxWidth: 820, margin: "auto", marginTop: 32, paddingBottom: 256 }}>
<StackGrid columnWidth={200} gutterWidth={16} gutterHeight={16}>
{galleryList}
</StackGrid>
</div>
)
}
Error
Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead. in NFTViewer (at App.jsx:271) in Route (at App.jsx:270) in Switch (at App.jsx:261) in Router (created by BrowserRouter) in BrowserRouter (at App.jsx:242) in div (at App.jsx:239) in App (at src/index.jsx:25) in ThemeSwitcherProvider (at src/index.jsx:24) in ApolloProvider (at src/index.jsx:2
CodePudding user response:
You should declare a separate async
function that triggers when data
changes.
Also, galleryList
should be a state so the page will re-render when it populates:
export default function DetailsViewer({}) {
const metadata = {};
const [galleryList, setGalleryList] = useState([]);
const [data, setData] = useState([]);
useEffect(() => {
const getNFTDetails = async () => {
try {
const response = await fetch('http://localhost:4000/getDetails');
const posts = await response.json();
setData(posts);
} catch (err) {
console.log(err);
}
};
getNFTDetails();
}, []);
useEffect(() => {
handleData();
}, [data]);
const handleData = async () => {
const list = [];
for (const a in data) {
metadata[a] = await fetchIPFSJSON(data[a].uri);
if (metadata[a].image) {
metadata[a].image = makeGatewayURL(metadata[a].image);
}
list.push(
<Card
style={{ width: 200 }}
key={data[a].name}
title={
<div>
{data[a].name}{' '}
<a target='_blank' rel='noreferrer'>
{/* <LinkOutlined /> */}
</a>
</div>
}
>
<img src={data[a].image} style={{ maxWidth: 130 }} />
</Card>
);
}
setGalleryList(list);
};
return (
<div
style={{
maxWidth: 820,
margin: 'auto',
marginTop: 32,
paddingBottom: 256,
}}
>
<StackGrid columnWidth={200} gutterWidth={16} gutterHeight={16}>
{galleryList}
</StackGrid>
</div>
);
}
CodePudding user response:
useEffect(() => {
const createGalleryList= async () => {
for (const a in data) {
metadata[a] = await fetchIPFSJSON(data[a].uri);
if (metadata[a].image) {
metadata[a].image = makeGatewayURL(metadata[a].image);
}
galleryList.push(
<Card
style={{ width: 200 }}
key={data[a].name}
title={
<div>
{data[a].name}{" "}
<a
target="_blank"
rel="noreferrer"
>
{/* <LinkOutlined /> */}
</a>
</div>
}
>
<img src={data[a].image} style={{ maxWidth: 130 }} />
</Card>,
);
}
}
createGalleryList()
}, [data]);
Create new useEffect and call the galleryList creation variable whenever data is changed. Don't use async in default functions and await in open. use galleryList as state var, at it renders when changed.