我正在尝试使用 Strapi 作为我的 cms 来构建一个超级简单的 React 博客。我遇到了一个问题,它试图在完成获取数据之前渲染数据。我正在尝试显示帖子图像,但我收到有关此处未定义属性的错误:
data.data.attributes.image.data.attributes.formats.large.url
。
这是ReactJS代码:
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import Navbar from "../components/Navbar";
function Post() {
const [data, setData] = useState({});
const { id } = useParams();
console.log("handle", id);
const fetchData = () => {
fetch(`http://localhost:1337/api/posts/${id}?populate=*`)
.then((response) => {
return response.json();
})
.then((d) => {
setData(d);
// console.log(data);
});
};
useEffect(() => {
fetchData();
}, []);
// console.log(data);
return (
<>
<Navbar />
<img
src={
"http://localhost:1337" +
data.data.attributes.image.data.attributes.formats.large.url
}
alt="image"
/>
</>
);
}
export default Post;
这是检索到的api数据:
{
"data": {
"id": 1,
"attributes": {
"postTitle": "First Post",
"datePosted": "2023-04-25",
"author": "Caleb",
"postText": "# Hello <u>**_World_**</u>\nThis is my very first blog post!\n\n![flower-right.png](http://localhost:1337/uploads/flower_right_b36ad9cd80.png)\n\n",
"createdAt": "2023-04-25T07:20:18.295Z",
"updatedAt": "2023-04-25T08:44:04.003Z",
"publishedAt": "2023-04-25T07:20:19.972Z",
"image": {
"data": {
"id": 1,
"attributes": {
"name": "unsplash_BhfE1IgcsA8-smaller.png",
"alternativeText": "header-image",
"caption": null,
"width": 2560,
"height": 1488,
"formats": {
"thumbnail": {
"name": "thumbnail_unsplash_BhfE1IgcsA8-smaller.png",
"hash": "thumbnail_unsplash_Bhf_E1_Igcs_A8_smaller_b163301e2d",
"ext": ".png",
"mime": "image/png",
"path": null,
"width": 245,
"height": 142,
"size": 57.28,
"url": "/uploads/thumbnail_unsplash_Bhf_E1_Igcs_A8_smaller_b163301e2d.png"
},
"small": {
"name": "small_unsplash_BhfE1IgcsA8-smaller.png",
"hash": "small_unsplash_Bhf_E1_Igcs_A8_smaller_b163301e2d",
"ext": ".png",
"mime": "image/png",
"path": null,
"width": 500,
"height": 291,
"size": 222.62,
"url": "/uploads/small_unsplash_Bhf_E1_Igcs_A8_smaller_b163301e2d.png"
},
"medium": {
"name": "medium_unsplash_BhfE1IgcsA8-smaller.png",
"hash": "medium_unsplash_Bhf_E1_Igcs_A8_smaller_b163301e2d",
"ext": ".png",
"mime": "image/png",
"path": null,
"width": 750,
"height": 436,
"size": 490.23,
"url": "/uploads/medium_unsplash_Bhf_E1_Igcs_A8_smaller_b163301e2d.png"
},
"large": {
"name": "large_unsplash_BhfE1IgcsA8-smaller.png",
"hash": "large_unsplash_Bhf_E1_Igcs_A8_smaller_b163301e2d",
"ext": ".png",
"mime": "image/png",
"path": null,
"width": 1000,
"height": 581,
"size": 884.48,
"url": "/uploads/large_unsplash_Bhf_E1_Igcs_A8_smaller_b163301e2d.png"
}
},
"hash": "unsplash_Bhf_E1_Igcs_A8_smaller_b163301e2d",
"ext": ".png",
"mime": "image/png",
"size": 1276.78,
"url": "/uploads/unsplash_Bhf_E1_Igcs_A8_smaller_b163301e2d.png",
"previewUrl": null,
"provider": "local",
"provider_metadata": null,
"createdAt": "2023-04-25T06:28:01.746Z",
"updatedAt": "2023-04-25T06:35:42.822Z"
}
}
}
}
},
"meta": {}
}
data
初始化为空对象:
const [data, setData] = useState({});
然后您尝试读取该空对象上的各种嵌套属性:
<img
src={
"http://localhost:1337" +
data.data.attributes.image.data.attributes.formats.large.url
}
alt="image"
/>
这显然会失败,因为
{}
没有名为 data
的属性,因此该属性为 undefined
,并且您无法读取 attributes
上的属性 undefined
(或任何属性)。
您也许可以使用可选链接:
<img
src={
"http://localhost:1337" +
data.data?.attributes?.image?.data?.attributes?.formats?.large?.url
}
alt="image"
/>
但请记住,这可能会在用户界面中显示损坏的图像。 或者,如果您在数据不可用时根本不想显示图像,请在显示图像之前检查数据是否可用:
{ data.data ? <img
src={
"http://localhost:1337" +
data.data?.attributes?.image?.data?.attributes?.formats?.large?.url
}
alt="image"
/> : null }
(如果您愿意,您可以将显式的
null
替换为默认图像、加载微调器或什么都不替换。)
您可以通过初始化为
undefined
来稍微简化检查:
const [data, setData] = useState();
然后检查对象本身而不是其属性:
{ data ? <img
src={
"http://localhost:1337" +
data.data?.attributes?.image?.data?.attributes?.formats?.large?.url
}
alt="image"
/> : null }
您必须在数据显示之前检查数据是否存在,这是一个示例。
return (
<>
<Navbar />
{!data ? ( //if data is currently empty then show the loading (or spinner)
<p>Loading...</p>
)
: (
<img
src={ "http://localhost:1337" +
data.data.attributes.image.data.attributes.formats.large.url
}
alt="image"
/>
)
}
)