I am fetching single type data from strapi api with React .map, but the single returned content is being rendered twice in this function:
{ Object.values(objecthere).map(({ }) => )}
Why is that, what am I doing wrong, and how can I make it render only once?
This code works well when fetching strapi’s collection types, but not the single type. I was expecting the code to render out the exact number of items in the array, which in this case is 1, not the same record twice.
Here’s the full code:
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;
The data that is being fetched is this:
{
"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": {
}
}
2
Answers
The problem is, that you set your objecthere variable to the content of the ‘data’ attribute in your json response.
This results in your objecthere variable being:
In your next step, you take all the values of this object as an array with Object.values(objecthere). This results in an array with two elements:
The .map() function then iterates over both elements in that array and thus gets called twice. Because you are referring to the objecthere variable itself inside the map function, you then get the exact same content rendered twice.
If your data is just a single type, you should just get rid of the Object.values(objecthere).map(({ }) function all together, because you access the attributes of objecthere directly anyway.
Just make sure, that you only access the objecthere attributes, if the variable is not null and that you initialize objecthere with null instead of an empty array:
Why does the map not accept any arguments? And should be place braces before and after your jsx inside map. Your map function should be like the follows.