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

How to style TextInput to display dollar amounts when using onChangeText and Redux in React Native

Struggling to format number input in a TextInput using the onChangeText function in React Native with Redux. Tried using .toFixed(2) function, but encountering an issue where it interprets the next digit as the first decimal and rounds back to 0 due to Re ...

Discover the secrets of applying a custom theme to a specific page with the power of Next.js 13 appDir. Unleash the potential

I've successfully set up my website with the Next.js 13 appDir and am using the next-theme workaround for appDir, as discussed in this issue: https://github.com/pacocoursey/next-themes/issues/152 My goal is to apply a theme specifically to the home p ...

Positioning a Few Navigation Menu Items on the Right Side of the Navigation Menu

I'm currently using the NavigationMenu component and I'm facing a challenge in achieving a specific layout. My goal is to have certain NavigationMenuItems aligned to the left side of the screen, while others (like login and theme change options) ...

The multi update feature is only compatible with $ operators when performing bulk find and update operations in node.js, as indicated by the Mongo

Why am I receiving the error message MongoError: multi update only works with $ operators when attempting to update multiple documents using the bulk find and update method. Things I have tried: var bulk = db.collection('users').initialize ...

Utilizing Flask for analyzing characteristics of text presented in JavaScript

My current variables consist of: myfruits = ['Apple', 'Banana', 'Lemon'] havefruit = [True, True, False] If the user input changes the values in havefruit, I need to implement JavaScript in my HTML file to display the entrie ...

Error: scrollreveal JavaScript is not properly defined

Desperately seeking guidance on a particular code snippet... window.sr = ScrollReveal({ reset: true }); sr.reveal('.whitecircle, .circleStatsItemBox, .circleStat', { duration: 200 }); function circle_program() { var divElement = $(&apo ...

Excessive alerts being produced within the loop

I am trying to remove a wine from a JSON wine list and I want to display an alert if the wine doesn't exist in the JSON file. However, the alert is popping up for every entry in the list. I am struggling to find a way to use an if statement before pro ...

The reactjs-toolbox radio button group remains unchanged

In my React application, I have implemented radio buttons using the following code: <RadioGroup name='steptype' className={css.ProcessStepRadioButtons} value={this.state.stepsData[stepNumber].stepType} onChang ...

Utilize Dinero.js to implement currency formatting for input fields in React applications

I am currently working on a form in React that requires certain input fields to be formatted as money currency. These inputs should be prefixed with the dollar sign ($), include commas for thousands separation, and have exactly two decimal points. During ...

A useful tip for emphasizing tags that have attributes with endings

Here is the HTML list I'm working with: <li class=​"info" data-info=​"" data-title=​"info 1" data-info-id=​"222643">…</li> <li class=​"info" data-info=​"" data-title=​"info 2" data-info-id=​"217145">…</li> ...

Tips for transferring the output of a JavaScript async function to a Python variable

var = driver.execute_script("setTimeout(function(){ return [1,2,3]; }, 1000);") Utilizing the Selenium method execute_script, I am attempting to extract data from a website using javascript and assign it to a python variable var. The challenge a ...

Utilize Javascript to load content dynamically while ensuring each page has a distinct link to individual content pages

As a newcomer to web development, I wanted to share my issue in hopes of finding a more efficient solution than what I've been attempting. Recently, I made changes to my website so that content is loaded dynamically using the jQuery load() function. T ...

In JavaScript, the JSON Object only stored the final result from a loop

I am currently working on an HTML Site that features 4 inputRange sliders. My goal is to store all values from these sliders in a nested JSON Object when a user clicks on a button. However, I have encountered an issue where my JavaScript code only saves th ...

Using Angular 4 to transfer data from a dynamic modal to a component

Currently implementing material design, I have set up a dialogService for dynamically loading MdDialog. My goal is to create a search dialog with filters that, upon submission, directs the user to a search-results component route. However, I am struggling ...

Issue with API causing Redux initial state problems

One issue I am facing is with fetching all products from the database and setting them into the Redux initial state. I created an action called SET_PRODUCTS_LIST where I pass the fetched products as payload in the component (I am using next js). Everything ...

Confusion about the unwinding of the call stack in the Graph Depth-

Issue with function: hasPathDFSBroken Fix implemented in: hasPathDFS The updated version includes a forced parameter to address the issue, which I would prefer to avoid. I'm trying to comprehend why in the broken version, when the call stack unwinds ...

Transforming the inputted URL into a clickable hyperlink

I have a text input field where any text entered is displayed below using angular.js. However, I am trying to convert any http URL entered into a clickable link. I found reference to the solution on this Stack Overflow page. Despite successfully converting ...

Issue with Ajax post redirection back to original page

I'm facing an issue with my ajax call where I send multiple checkbox values to a php file for processing and updating the database. The post request and database updates are successful, but the page doesn't return to the calling php file automati ...

At what point is the rendering process of ng-switch completed?

I am currently utilizing ui-router and facing a challenge in instantiating a widget that requires a DOM element specified by its id as a parameter. The specific DOM element is nested within a <div ng-switch>, and I need to ensure the widget construct ...

Find the time matching in a time string using Javascript

I need to extract the time in the format "HH:MM:SS" from a string like "HH:MM:SS CEST". How can I achieve this without including any additional strings such as CEST? ...