Using the map function to iterate over an array of objects retrieved from GetStaticProps in NextJS

Currently, I am working on a mdx blog within the NextJS framework. To achieve this, I have implemented a function called getPostDataByCategory(category) in posts.js located under lib. This function is responsible for filtering posts based on categories.

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 };
}

The filteredPosts data is obtained through getStaticProps within categories/[categories].js as shown below:

export async function getStaticProps({ params }) {
let posts = await getPostDataByCategory(params.categories);
  const filteredPosts = JSON.parse(JSON.stringify(posts));

  return {
    props: {
      filteredPosts,
    },
  };
}

Subsequently, the filteredPosts are received and displayed in a component named Category:

export default function Category({ filteredPosts }) {
  
  return (
    <Layout>
      <ul>
        {filteredPosts.map((posts) => (
          <li key={posts.slug}>
            <p>{posts.title}</p>
          </li>
        ))}
      </ul>
    </Layout>
  );
}

Unfortunately, an error occurs stating TypeError: filteredPosts.map is not a function

This error indicates that filteredPosts is not recognized as an array, requiring either object destructuring or conversion into an array.

I would greatly appreciate any assistance or insights. Thank you in advance.

I have extensively researched methods to convert an array of Objects into an array of arrays, but most solutions appear complex for my specific case. There has to be a simpler way to accomplish this task.

Answer №1

You have a mix-up in the object key names and you are unnecessarily pushing nested arrays, causing confusion and problems with your mapping operations. The majority of the fixes can be implemented in getPostDataByCategory to restructure how your data is organized.

To begin, the .filter() method generates a new array, so the following code snippet instructs to push an array (resulting from your filter()) into the filteredPosts array:

let filteredPosts = [];

filteredPosts.push(
  allPostsData.filter((post) => post.categories.includes(category)) // pushing a new array into the `filteredPosts` array
);

This results in nested arrays, which is not desired here. Instead, you just need to assign fileredPost directly to the outcome of .filter():

const filteredPosts = allPostsData.filter((post) => post.categories.includes(category));

Subsequently, you are returning an object with a filteredPosts key:

return { filteredPosts };

This is essentially equivalent to returning an object like this (refer to short-hand property names):

return { filteredPosts: filteredPosts};

Hence, your object contains a filteredPosts posts key, holding the array that resides in the filteredPosts variable. Given that you are only returning one thing (i.e., the filtered posts), you can simplify by skipping the creation of the object, making now your getPostDataByCategory return an array:

return filteredPosts;

With these modifications in place for getPostDataByCategory, you can proceed to adjust how getStaticProps is utilized (check the code comments):

export async function getStaticProps({ params }) {
  const filteredPosts = getPostDataByCategory(params.categories); // there's no need to `await` the `getPostDataByCategory()` as it's not `async` and doesn't yield a Promise.
  
  // Avoid creating a deep copy: const filteredPosts = JSON.parse(JSON.stringify(posts));

  return {
    props: {
      filteredPosts, // filteredPosts is now an array of objects
    },
  };
}

Now you can correctly map your filteredPosts as intended:

{filteredPosts.map((posts) => (
  <li key={posts.slug}>
    <p>{posts.title}</p>
  </li>
))}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

jQuery's feature to select all elements except one and its children appears to be malfunctioning in Safari

My goal is fairly simple. I want to make the entire section clickable, except for the span and anything beneath it, so that the link redirects elsewhere. <section id="id" class="message"> <div class="message_body"> <font color="color"> ...

Is there a way to serialize a dynamically loaded element with jQuery?

So here's the situation: I have a list of tags that needs to be updated using an ajax call. First, I clear out the <ul> that holds the tags. Then, with the response from the ajax call, I populate the <ul> with new <li> elements re ...

Can anyone suggest a method for adding comments and improving the organization of a bower.json file?

Managing a large project with numerous bower dependencies can be challenging. It's often unclear whether these dependencies are still being used or if the specified versions are necessary for a reason. It would be ideal to have the ability to add comm ...

Properties around the globe with Express & Handlebars

Currently, I am utilizing Handlebars (specifically express3-handlebars) for templates and Passport for authentication in my NodeJS application. Everything is functioning smoothly, but I have been contemplating if there is a method to globally pass the req. ...

Unable to establish connection with Uploadthing due to a timeout error

I am facing timeout errors while setting up the upload feature. app/api/uploadthing/core.ts import { createUploadthing, type FileRouter } from "uploadthing/next"; import { auth } from "@clerk/nextjs"; const handleAuth = () => { c ...

Create a connection between a div and a React component, allowing for the seamless transfer of

I'm looking to implement a feature where clicking on a specific div will redirect the user to another page, similar to React Router. However, I currently lack the knowledge to make it happen. Below is the code snippet in question: const Card: React.FC ...

Why is my JSON parse function returning an empty string?

Not sure if the issue lies with VueJS or JS itself. Within my database, I have a string (converted from a JS Object using JSON.stringify()) that appears as follows: {"type":5,"values":{"7":"/data/images/structured-content/64-7-scico.jpg","8":"<b>we ...

How does the Rx subscribe function maintain its context without the need to explicitly pass it along

Currently, I am utilizing Rx with Angular2 and making use of the Subscribe method. What intrigues me is that the callbacks of the method are able to retain the context of the component (or class) that initiated it without needing any explicit reference pas ...

Facing difficulties in resetting the time for a countdown in React

I've implemented the react-countdown library to create a timer, but I'm facing an issue with resetting the timer once it reaches zero. The timer should restart again and continue running. Take a look at my code: export default function App() { ...

Position an element with absolute positioning to the right edge of a relative element

I have a situation where I need to align the end of a position absolute element with the end of a relative element, but the relative element's width is not fixed and may vary based on content. This scenario arises as I am creating a custom dropdown m ...

Tips for utilizing regex to locate words and spaces within a text?

I'm feeling so frustrated and lost right now. Any help you can offer would be greatly appreciated. I am currently dealing with an issue in Katex and Guppy keyboard. My goal is to create a regex that will identify the word matrix, locate the slash that ...

Tips for customizing a single row in v-data-table? [Vuetify]

My goal is to change the background color of a specific row that contains an entry matching the value of lowestEntry. <v-col cols="8"> <v-data-table :loading="loadEntryTable" loading-text="Searching for data..." ...

Encountering a 405 error when attempting to send a request through an express route in a Next

After deploying my Express js routes in Next js on hosting, I encountered an error 405 when sending requests to the route. However, everything works fine when I test it on localhost. I'm puzzled by this issue. Can anyone help me understand what' ...

Wait for NodeJS to finish executing the mySQL query

I am attempting to send an object from the controller to the view. To keep my queries separate from the controller, I am loading a JS object (model). My model structure is as follows: function MyDatabase(req) { this._request = req; this._connection = ...

Encountering a 500 error when deploying Next.js with Mongodb, mongoose, and Vercel (functions properly on local host)

I'm currently in the process of deploying my Next.js application that utilizes MongoDB and Mongoose. While everything runs smoothly on localhost, I encounter an error when deploying to Vercel as shown in the logs: Despite double-checking my environme ...

Attempting to store a specific h1 text.event as a variable, allowing it to be saved upon input of the initial letter

After typing the second key, you can continue to input more characters as desired. It is possible to customize the text displayed in the h1 using your own name or any other text of your preference without needing a textbox. $(document).keypress(functio ...

Exploring the history and present state of Vue lifecycle hooks

Is there a way to access previous and current data in the updated lifecycle hook in Vue, similar to React? I want to be able to scroll a list of elements to the very bottom, but for this I need: The already rendered updated DOM (to calculate the scroll) ...

Next Image is encountering the ERR_TLS_CERT_ALTNAME_INVALID error when attempting to load an external URL

I have set up a custom domain with a subdomain that points to an AWS S3 bucket, such as images.domain.com. Users are able to upload images and view them in the bucket. The URL for each image is stored in the user's data in the database. However, when ...

Challenges faced with Vuetify's vertical and non-linear stepper components

I've been struggling to grasp the concept of Vuetify's stepper feature. Despite my efforts, I haven't been successful in combining different steppers from their page that each have elements I need but lack others. One example is this one on ...

How to change a string from utf-8 to iso-8859-1 using Javascript

Although it may seem unpleasant, it is essential. I am facing an issue with a HTML form on my website that uses utf-8 charset but is sent to a server operating with iso-8859-1 charset. The problem arises when the server fails to interpret characters commo ...