I am building a mdx blog in NextJS. For this I have created a function getPostDataByCategory(category) in posts.js under lib to filtering posts based on category.
getPostDataByCategory(category) {
const fileNames = fs.readdirSync(postsDirectory);
// allPostsData to read all the file contents parsed using gray-matter
const allPostsData = fileNames.map((fileName) => {
...
}
let filteredPosts = [];
filteredPosts.push(
allPostsData.filter((post) => post.categories.includes(category))
);
return { filteredPosts };
}
I am receiving the filteredPosts in getStaticProps in categories/[categories].js as under:
export async function getStaticProps({ params }) {
let posts = await getPostDataByCategory(params.categories);
const filteredPosts = JSON.parse(JSON.stringify(posts));
return {
props: {
filteredPosts,
},
};
}
Thereafter I receive the filteredPosts in Category as:
export default function Category({ filteredPosts }) {
return (
<Layout>
<ul>
{filteredPosts.map((posts) => (
<li key={posts.slug}>
<p>{posts.title}</p>
</li>
))}
</ul>
</Layout>
);
}
However it gives me an error as TypeError: filteredPosts.map is not a function
I understand this error is due to the fact that filteredPosts is not an array and object destructing has to be done or it has to be converted to an array.
Any help is appreciated. Thanks beforehand.
I searched extensively for converting the array of Objects to array of arrays but they all seem complex for my usecase. There must be a simpler way of doing this.
You're mixing up object key names and also pushing nested arrays where it's not needed, causing confusion and issues with your mapping operations. Most of the fixes can be made to
getPostDataByCategoryto clean up how your date is structured.Firstly, the
.filter()method returns a new array, so the below code says to push an array (the one returned by yourfilter()) into thefilteredPostsarray:This ends up with you having nested arrays which isn't what you want here. You just need to assign
fileredPostdirectly to the result of.filter():Next, you then return an object with a
filteredPostskey:This is equivalent to returning an object like so (see short-hand property names):
So your object has a
filteredPostsposts key, that holds the array that's in thefilteredPostsvariable. Since you're returning just one thing (ie: the filtered posts), you can avoid creating the object so that now yourgetPostDataByCategoryreturns an array:With these changes made to
getPostDataByCategory, you can now update howgetStaticPropsis used (see code comments):Now you can map your
filteredPostscorrectly as you were trying to do: