我正在使用 React .map 从 strapi api 获取单一类型的数据,但是单一返回的内容在这个函数中被渲染了两次:
{ Object.values(objecthere).map(({ }) => )}
为什么会这样,我做错了什么,我怎样才能让它只渲染一次? 此代码在获取 strapi 的集合类型时效果很好,但不是单一类型。我期待代码呈现出数组中项目的确切数量,在本例中为 1,两次不是相同的记录。
完整代码如下:
import { useEffect, useState } from 'react';
import { Link } from "react-router-dom";
// Parses the JSON returned by a network request
const parseJSON = (resp) => (resp.json ? resp.json() : resp);
// Checks if a network request came back fine, and throws an error if not
const checkStatus = (resp) => {
if (resp.status >= 200 && resp.status < 300) {
return resp;
}
return parseJSON(resp).then(resp => {
throw resp;
});
};
const headers = { 'Content-Type': 'application/json' };
const BoxComponent = () => {
const [error, setError] = useState(null);
const [objecthere, setObjecthere] = useState([]);
useEffect(() => {
fetch('http://localhost:1337/api/boxdata?populate=*', { headers, method: 'GET' })
.then(checkStatus)
.then(parseJSON)
.then(({ data }) => setObjecthere(data))
.catch((error) => setError(error))
}, [])
if (error) {
// Print errors if any
return <div>An error occured: {error.message}</div>;
}
return (
<div className="container">
{ Object.values(objecthere).map(({ }) =>
<div key={ objecthere.id }>
<section className="py-4 py-xl-5">
<div className="container">
<h2 className="font-weight-bold text-white mb-3">{ objecthere.id } { objecthere.attributes.TheBox.Title}</h2>
<p className="mb-4">{ objecthere.attributes.TheBox.TextContent}</p><Link to="/contact"><span className="btn btn-light btn-lg" role="button">{ objecthere.attributes.TheBox.ButtonText }</span></Link>
</div>
</section>
</div>
)}
</div>
);
};
export default BoxComponent;
正在获取的数据是这样的:
{
"data": {
"id": 1,
"attributes": {
"createdAt": "2023-03-19T11:04:03.351Z",
"updatedAt": "2023-03-19T12:08:17.995Z",
"publishedAt": "2023-03-19T11:06:53.616Z",
"TheBox": {
"id": 1,
"Title": "Title here",
"TextContent": "Tincidunt laoreet leo, adipiscing taciti tempor. Primis senectus sapien, risus donec ad fusce augue interdum.!",
"ButtonText": "Read more",
"ButtonURL": "#"
}
}
},
"meta": {
}
}
问题是,您将 objecthere 变量设置为 json 响应中“数据”属性的内容。
这导致您的 objecthere 变量为:
{
"id": 1,
"attributes": {
"createdAt": "2023-03-19T11:04:03.351Z",
"updatedAt": "2023-03-19T12:08:17.995Z",
"publishedAt": "2023-03-19T11:06:53.616Z",
"TheBox": {
"id": 1,
"Title": "Title here",
"TextContent": "Tincidunt laoreet leo, adipiscing taciti tempor. Primis senectus sapien, risus donec ad fusce augue interdum.!",
"ButtonText": "Read more",
"ButtonURL": "#"
}
}
}
在你的下一步中,你将这个对象的所有值作为一个带有 Object.values(objecthere) 的数组。这导致一个包含两个元素的数组:
[
1,
{
"createdAt": "2023-03-19T11:04:03.351Z",
"updatedAt": "2023-03-19T12:08:17.995Z",
"publishedAt": "2023-03-19T11:06:53.616Z",
"TheBox": {
"id": 1,
"Title": "Title here",
"TextContent": "Tincidunt laoreet leo, adipiscing taciti tempor. Primis senectus sapien, risus donec ad fusce augue interdum.!",
"ButtonText": "Read more",
"ButtonURL": "#"
}
}
]
.map() 函数然后迭代该数组中的两个元素,因此被调用两次。因为您在 map 函数中引用了 objecthere 变量本身,所以您会得到两次呈现完全相同的内容。
如果你的数据只是单一类型,你应该把 Object.values(objecthere).map(({ }) 函数一起去掉,因为无论如何你直接访问 objecthere 的属性。
只需确保,如果变量不为 null 并且您使用 null 而不是空数组初始化 objecthere,则您只能访问 objecthere 属性:
const [objecthere, setObjecthere] = useState(null);
[...]
return (
<div className="container">
{ objecthere != null &&
<div key={ objecthere.id }>
<section className="py-4 py-xl-5">
<div className="container">
<h2 className="font-weight-bold text-white mb-3">{ objecthere.id } { objecthere.attributes.TheBox.Title}</h2>
<p className="mb-4">{ objecthere.attributes.TheBox.TextContent}</p><Link to="/contact"><span className="btn btn-light btn-lg" role="button">{ objecthere.attributes.TheBox.ButtonText }</span></Link>
</div>
</section>
</div>
}
</div>
);
为什么地图不接受任何参数?并且应该在你的 jsx inside map 前后放置大括号。您的地图功能应该如下所示。
return (
<div className="container">
{ Object.values(objecthere).map((value) => (
<div key={ value.id }>
<section className="py-4 py-xl-5">
<div className="container">
<h2 className="font-weight-bold text-white mb-3">{ value.id } { value.attributes.TheBox.Title}</h2>
<p className="mb-4">{ value.attributes.TheBox.TextContent}</p><Link to="/contact"><span className="btn btn-light btn-lg" role="button">{ value.attributes.TheBox.ButtonText }</span></Link>
</div>
</section>
</div>
)}
</div>)
);