【问题标题】:Create dynamic routes by id from Next JS pages api从 Next JS pages api 通过 id 创建动态路由
【发布时间】:2022-01-13 02:48:06
【问题描述】:

我有一个页面,其中包含一个名为stories 的对象列表,它以数组的形式显示我的所有故事。我还有一个显示个人故事的详细信息页面。

我想单击列表中任何给定故事的链接,然后它会将我导航到单个故事。我想使用_id 作为 URL 的动态部分,如下面的 GraphQL 所示。

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

在我拥有的 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]()
}

在我拥有的故事列表页面上

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

这很好并且有效。

**然后在每个故事的详细信息页面上 [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() }
        }
          // 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 }
    }
}

错误

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

问题

我要做的就是单击任何故事链接,然后通过_id 将我带到详细信息页面。我尝试了一些事情,但我做错了(或某些事情)。

任何帮助将不胜感激。

之后编辑。我得到的错误。我无法将结果映射到 getStaticPaths

【问题讨论】:

  • API 路由是否返回了预期的数据? GraphQL 请求是否返回了预期的响应?

标签: javascript async-await graphql next.js nextjs-dynamic-routing


【解决方案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 }
    }
}

【讨论】:

  • 非常感谢@Devdreamsolution。我的 getStaticPath 地图仍然存在问题。你能看看吗?我在底部更新了错误图片
  • 服务器未在您的 getStaticPath 中定义。
  • 恐怕不是,我已经在getStaticPath中定义了。仍然得到未定义的错误映射。
  • 另外,当我在 getStaticProps 中使用 console.log(data) 时,我得到了 undefined
  • 我建议您使用以下 /api/entries/allStories/MANUAL_ID 检查您的 API
【解决方案2】:

取消注释

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

【讨论】:

  • 非常感谢@Sadeek - 我没有注释,但我的 getStaticPaths 仍然出现错误。看看问题底部的错误。关于我的地图功能的一些事情
【解决方案3】:
// 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] }
    }
}

【讨论】:

    猜你喜欢
    • 2010-10-25
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 2014-02-02
    • 2020-01-24
    • 2021-08-09
    相关资源
    最近更新 更多