1

I have a page with a list of objects called stories that displays all my stories in an array. I also have a detail page with displays an individual story.

I want to click on a link on any given story on the list, then it will navigate me to the individual story. I want to use _id as my dynamic part of the URL, as shown in the GraphQL below.

My Graphql

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

IN MY PAGES API I HAVE

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]()
}

ON THE STORY LIST PAGE I HAVE

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 is fine and works.

**AND THEN ON THE DETAIL PAGE FOR EACH INDIVIDUAL STORY [storyId].js I HAVE **

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() }
        }
          // trying to get the _id from each story 
    })
    return {
        paths,
        fallback: false
    }
}

    export const getStaticProps = async (context) => {
    const { storyId } = context.query;    // Your dynamic page is [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
    console.log(res)
    const { data } = await res.json();
    return {
        props: { story: data }
    }
}

ERROR

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

QUESTION

All I want to do is click on any story link, then it takes me to the details page, via the _id. I have tried a few things but I'm doing something (or some things) wrong.

Any help will be greatly appreciated.

EDIT AFTER. ERROR I'M GETTING. I'm not able to map my results on getStaticPaths

enter image description here

Shingai Munyuki
  • 551
  • 1
  • 11
  • 25

3 Answers3

1
export const getStaticProps = async (context) => {
    const { storyId } = context.query;    // Your dynamic page is [storyId].js
    const server = "YOUR SERVER VARIABLE";

    const res = await fetch(`${server}/api/entries/allStories/${storyId}`);
      // trying to get the params._id from each story
    const { data } = await res.json();
    return {
        props: { story: data }
    }
}
0

uncomment

const router = useRouter()
const storyId = router.query.storyId

  • Thanks a lot @Sadeek - I have uncommented but i'm still getting an error on my getStaticPaths. Take a look at the error at the bottom of the question. Something about my map function – Shingai Munyuki Dec 08 '21 at 14:39
0
// some helpful links
// 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;    // Your dynamic page is [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 the calling the single api (just a fix not recommended to access [0] directly )
    return {
        props: { story: data.filter(story => story._id === storyId)[0] }
    }
}

dijux
  • 541
  • 5
  • 8