Reputation: 611
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
Upvotes: 1
Views: 7736
Reputation: 571
// 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] }
}
}
Upvotes: 0
Reputation: 519
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 }
}
}
Upvotes: 1
Reputation: 1
uncomment
const router = useRouter()
const storyId = router.query.storyId
Upvotes: 0