I have an issue here trying to access a Post array that has inside a categories array. So if I console.log the data I see something like this:
{
posts: [
{
_createdAt: '2021-10-23T05:02:26Z',
_type: 'post',
_updatedAt: '2021-10-23T23:28:09Z',
body: [Array],
categories: [Array], <<<<-- this is the one I need to access
mainImage: [Object],
publishedAt: '2021-10-23T18:30:00.000Z',
slug: [Object],
title: 'Post Name title goes here'
}
.
.
.
]
}
I need to access the categories Array inside my Post Array,but I'm having a really hard time trying to access it. I currently tried something like this:
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
{posts.map(
({
_id,
title = "",
slug = "",
_createdAt = "",
mainImage = "",
categories = "",
}) =>
slug && (
<div className="shadow-lg rounded-lg bg-white pb-5" key={_id}>
<div className="px-6 py-4 text-left">
<div className="flex flex-row mt-4 items-center">
{categories && (
<ul className="inline-flex my-3" style={{ listStyle: "none" }}>
{categories.map((category) => (
<li key={category}>
<span
className="mx-2
items-center
justify-center
px-2
py-1
text-xs
font-bold"
>
{category}
</span>
</li>
))}
</ul>
)}
</div>
</div>
</div>
)
)}
</div>;
when I do this I get the following error:
Objects are not valid as a React child (found: object with keys {_key, _ref, _type}). If you meant to render a collection of children, use an array instead.
I even tried to do something like this:
{posts.categories.map((category) => (
<li key={category}>
<span
className="mx-2
items-center
justify-center
px-2
py-1
text-xs
font-bold"
>
{category}
</span>
</li>
));
}
But still no luck. Any ideas of what am I doing wrong? Thanks!
CodePudding user response:
Do you want an array of arrays?
const arrayOfArrayOfCategories = posts.map(post => post.categories);
If you want to access the first post's categories:
const { categories } = posts[0];
CodePudding user response:
Always best to split code up to make it easier. I would create seperate component for Post that takes in post
as a prop. Then import it where you need to.
Post.js
function Post({ post }) {
const { categories } = post;
function renderCategories() {
return categories.map((category) => {
return <span>{category}</span>;
});
}
return <div>{renderCategories()}</div>;
}
export default Post;
App.js
import Post from "./Post";
function App() {
const posts = [
{
_createdAt: "2021-10-23T05:02:26Z",
_type: "post",
_updatedAt: "2021-10-23T23:28:09Z",
body: [Array],
categories: ["categoiry", "sfsdfd", "eosiefoise", "dseuhse"],
mainImage: [Object],
publishedAt: "2021-10-23T18:30:00.000Z",
slug: [Object],
title: "Post Name title goes here",
},
{
_createdAt: "2021-10-23T05:02:26Z",
_type: "post",
_updatedAt: "2021-10-23T23:28:09Z",
body: [Array],
categories: ["categoiry", "sfsdfd", "eosiefoise", "dseuhse"],
mainImage: [Object],
publishedAt: "2021-10-23T18:30:00.000Z",
slug: [Object],
title: "Post Name title goes here",
},
{
_createdAt: "2021-10-23T05:02:26Z",
_type: "post",
_updatedAt: "2021-10-23T23:28:09Z",
body: [Array],
categories: ["categoiry", "sfsdfd", "eosiefoise", "dseuhse"],
mainImage: [Object],
publishedAt: "2021-10-23T18:30:00.000Z",
slug: [Object],
title: "Post Name title goes here",
},
];
function renderPosts() {
return posts.map((post) => {
return <Post post={post} />;
});
}
return <div>{renderPosts()}</div>;
}
CodePudding user response:
From the error it looks like categories
is an array of references. You'll want to resolve the references in your GROQ query (something like "categories": categories[]->
) and then on your front end, you'll need to use properties of each category
(created when you map over categories
) rather than the whole object itself. You'll want to map over categories
as you've done, but inside the map callback function you won't ever directly refer to the whole object.
Rather than:
{posts.categories.map((category) => (
<li key={category}>
<span>
{category}
</span>
</li>
));
}
you'll want to do something like (assuming a text
property exists):
{posts.categories.map((category) => (
<li key={category._id}>
<span>
{category.text}
</span>
</li>
));
}