Utilize Next JS pages api to generate dynamic routes based on unique ids

In the content of my website, there is a collection of objects named stories that are displayed as an array. Additionally, I have a section where each individual story is showcased in detail.

I intend to enable users to click on any story link within the list and be directed to the detailed page for that specific story. Utilizing the _id as a dynamic component of the URL is key, as illustrated below in the GraphQL code snippet.

The Graphql Query

export const listAllStories = () => {
  const query = gql`
    query StoryEntries($size: Int) {
      storyEntries(_size: $size) {
        data {
          _id
          _ts
          name
          premises{
            data{
              _id
              content
            }
          }
          createdAt
        }
      }
    }
  `

  return graphQLClient
      .request(query, { size: 999 })
      .then(({ storyEntries: { data } }) => data)
}

Within My Pages API

export default async function handler(req, res) {
  const handlers = {
    GET: async () => {
      const storyEntries = await listAllStories()
      res.json(storyEntries)
    },
  }

  if (!handlers[req.method]) {
    return res.status(405).end()
  }

  await handlers[req.method]()
}

In The Overview Page For Each Story

const ENTRIES_PATH = '/api/entries/allStories'

const useEntriesFlow = ({ initialEntries }) => {
    const { data: entries } = useSWR(ENTRIES_PATH, {
        initialData: initialEntries,
    })

    const EntryItem = ({ entry }) => (
         <>
            {entries?.map((entry) => (
                  {entry.name}
       <Link href="/story/[storyId]" as={`/story/${entry._id}`}>
                                <a>Go</a>
                            </Link>
             ))}
         </>
    )

export const getStaticProps = async () => ({
    props: {
        initialEntries: await listAllStories(),
    },
    revalidate: 1,
})

This implementation functions correctly and meets the requirements.

**On The Detailed Page For Each Individual Story [storyId].js **

export default function Story({story}) {

    const router = useRouter()
    const storyId = router.query.storyId
    return(
        <>
            <h5>hello {story._id}</h5>
        </>
    )
}

export const getStaticPaths = async () => {
    const res = await fetch(`${server}/api/entries/allStories/`);
    const { data } = await res.json();
    const paths = data.map(story => {
        return {
            params: { id: story._id.toString() }
        }
          // Extracting the _id from each story 
    })
    return {
        paths,
        fallback: false
    }
}

    export const getStaticProps = async (context) => {
    const { storyId } = context.query;    
    const server = "http://localhost:3000";

    const res = await fetch(`${server}/api/entries/allStories/${storyId}`);
    console.log(res)
    const { data } = await res.json();
    return {
        props: { story: data }
    }
}

Error Message

TypeError: Cannot read properties of undefined (reading 'map')

Question

The main objective is to seamlessly navigate between the story list and individual story details using the unique _id associated with each story. Despite numerous attempts, I seem to be encountering issues or errors along the way.

Your assistance and guidance on this matter would be sincerely appreciated.

Edit After Receiving An Error: There appears to be difficulty in mapping the results obtained in the getStaticPaths method.

https://i.stack.imgur.com/e1xDs.png

Answer №1

const fetchData = async (context) => {
    const { postId } = context.query;
    const serverUrl = "YOUR SERVER URL";

    const response = await fetch(`${serverUrl}/api/posts/getPost/${postId}`);
      
    const { postData } = await response.json();
    return {
        fetchedData: { post: postData }
    }
}

Answer №2

remove comment

let router = useRouter()
let id = router.query.storyId

Answer №3

// check out these useful resources
// https://nextjs.org/docs/basic-features/data-fetching#the-paths-key-required
// https://stackoverflow.com/questions/65783199/error-getstaticpaths-is-required-for-dynamic-ssg-pages-and-is-missing-for-xxx

export const getStaticPaths = async () => {
    const server = "http://localhost:3000";

    const data = await fetch(`${server}/api/entries/allStories/`).then(res => res.json() )

    const paths = data.map(({_id}) => ({
        params: { storyId: _id },
    }))

    return {
        paths,
        fallback: false
    }
}

export const getStaticProps = async (context) => {

    const storyId = context.params.storyId;    // Dynamic page [storyId].js
    const server = "http://localhost:3000";

    // const res = await fetch(`${server}/api/entries/allStories/${storyId}`);
    // trying to get the params._id from each story 
    // single api call (here)
    const res = await fetch(`${server}/api/entries/allStories/`);
    // removing const { data } because the data will be returned when calling res.json()
    const data = await res.json();
    // instead of calling the single API (fix not recommended to access [0] directly )
    return {
        props: { story: data.filter(story => story._id === storyId)[0] }
    }
}

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

Utilizing AJAX for XML data parsing

I need help with formatting XML data into a table. The code I've written isn't working as expected. The XML data is structured in branches, causing it to not display correctly. Can someone assist me in fixing this issue? <!DOCTYPE html> &l ...

Tips for navigating through complex JSON structures with JavaScript or JQuery

I'm currently navigating the complexities of parsing a multi-level JSON array as a newcomer to JSON. I am seeking solutions using either JavaScript or jQuery. My goal is to extract the application id, application description, and Product description f ...

Cannot display GIF file from the SRC directory in a React application

I am trying to display a gif from the "/src/images" folder in my component, but I keep getting my "old" value displayed instead. What could be causing this issue? Snippet from Danke.js site: import Confetti from "../images/confetti.gif"; <Box sx={{ ju ...

Cannot locate module using absolute paths in React Native with Typescript

I recently initiated a new project and am currently in the process of setting up an absolute path by referencing this informative article: https://medium.com/geekculture/making-life-easier-with-... Despite closely following the steps outlined, I'm en ...

Struggling with using flexboxes and creating animated elements

Seeking assistance with animating the search bar on a website project. The animation is functioning, but the search input abruptly moves when the animation starts, as shown in this GIF: I am utilizing jQuery for the animation because I also want to implem ...

What is preventing my function from retrieving user input from an ngForm?

I'm currently working on my angular component's class. I am attempting to gather user input from a form and create an array of words from that input. The "data" parameter in my submit function is the 'value' attribute of the ngForm. Fo ...

Struggling with displaying Firebase data in React

I am facing an issue with rendering data fetched from Firebase onto the screen. The problem arises when I attempt to call the function that retrieves data from the database inside the componentDidMount() lifecycle method. Surprisingly, the function does no ...

The mute feature in Discord.js along with setting up a muterole seems to be malfunctioning and encountering errors

Currently, I am working on implementing a mute command feature. The main goal is to have the bot automatically create a role called Muted if it doesn't already exist, and then overwrite the permissions for every channel to prevent users with that role ...

Trouble with downloading a file from an HTML hyperlink

When I attempt to download a file from my file folder using the absolute path <a href='N:\myName\test.xlsx'>download</a>, the file opens directly instead of downloading. However, if I use the relative path <a href=&apos ...

What's the best way to use JavaScript to obtain the width of a 'css-pixel' based on a media query?

While there have been discussions on how to determine device sizes using media queries like Twitter Bootstrap, I am looking for a reliable way to achieve the same output using JavaScript. Specifically, I want to get the CSS media query pixel number rather ...

The strange behavior of !important, display:none, and .height()

While working with a piece of JS code yesterday, I stumbled upon something peculiar. There was a div element that was initially hidden using display:none, and I was utilizing its height in some JavaScript calculations. Everything was functioning properly u ...

The issue of the "port" attribute not working for remotePatterns in the Image component has been identified in Next.js 13's next.config.js

I've encountered an issue with the code snippet below. I'm attempting to utilize remotePatterns in my next.config.js file to enable external images. Strangely, when I set the port to an empty string "", it functions correctly. However, specifying ...

Utilizing Unidirectional Binding within an AngularJS Directive

I have a directive set up here: myApp.directive('stoplight', function() { return { restrict:'E', transclude: true, scope: { value: '@' }, link: function(scope, element) ...

Using Vue.js along with vuex and axios allows for data retrieval only upon the second load

After creating a Vue.js app with vuex as a central store and using axios for basic API calls, I implemented the following store action: loadConstituencyByAreaCodeAndParliament({commit}, {parliament_id, area_code}) { axios.get('/cc-api/area-code/ ...

The state in useState is failing to update correctly following selections made within the dropdown menus

I am currently facing an issue with my dropdown disabling function, which is not enabling the dropdown properly. I suspect that this is due to asynchronous problems stemming from the use of useState. const [homeSelect, setHomeSelect] = useState('Home& ...

What is the best approach to isolating tests for a CRUD App using Playwright?

In attempting to follow the recommendations in the Playwright documentation insisting on isolated tests, I am running into some practical difficulties. Initially, my approach involved truncating the table after each test to clear all records, with subseque ...

Grabbing an AJAX Request

Currently, I am working on a Firefox extension that is designed to analyze the HTML content of web pages after they have been loaded in the browser. While I have successfully captured events like form submissions and link clicks, I am facing an issue wit ...

Are website files safe to store in the public_html directory?

Previously, I had a backend built in Laravel and a frontend in React. Recently, someone converted my frontend to Next.js. I noticed that he placed both the frontend and backend in the public folder. Prior to this conversion, I had the website app in a fol ...

What is the best way to integrate Next.js with Strapi (or the other way around)?

My goal is to develop an application utilizing Next.js for the frontend, fetching data from a Strapi API hosted on the same server. The plan is to have Strapi handle API and admin routes, while Next.js manages all other routes. I intend to use fetch in Nex ...

When you use Greasemonkey to click a link embedded within the content

In need of assistance with clicking a dynamic link using Greasemonkey. The only static part of the code is the text 'Attack This Player'. The href attribute of the link changes depending on the page. Here is my current code: function click_elem ...