在 NextJS 中使用“getStaticPaths”和“getStaticProps”创建动态路由
Posted
技术标签:
【中文标题】在 NextJS 中使用“getStaticPaths”和“getStaticProps”创建动态路由【英文标题】:Creating Dynamic Routes using 'getStaticPaths' and 'getStaticProps' in NextJS 【发布时间】:2020-10-18 17:56:44 【问题描述】:我正在尝试根据每本书的 "id" 查询字符串创建动态页面,以在单独的页面上显示单个书籍的详细信息(即标题/作者)。在previous question 我问过,用户的回答非常有帮助,我对如何正确使用getStaticPaths
和getStaticProps
有了更好的理解。但是,我的代码中并没有详细说明如何执行此操作。
这是基本设置和上下文。
-
我正在运行 NextJS 9.4,并希望使用 API 端点而不是直接查询数据库。
图书数据从 MongoDB Atlas 数据库中提取并使用 Mongoose
MongoDB 中的文档具有 "_id" 作为唯一 ID。
我已尝试合并现有的 Github 示例和 NextJS 文档并从中学习,但我仍然收到以下错误。
Error: A required parameter (id) was not provided as a string in getStaticPaths for /book/[id]
这是我到目前为止的代码。我现在尽量保持代码干净。
export default function Book( book )
return (
<article>
<h1>Book Details Page</h1>
<p>book.title</p>
<p>book.author</p>
</article>
)
export async function getStaticPaths()
const url = `$baseUrl/api/books/books`
const response = await axios.get(url);
const books = response.data
const paths = books.map((book) => (
params: id: book.id ,
))
return paths, fallback: false
export async function getStaticProps( params )
const url = `$baseUrl/api/books/books/$params.id`
const res = await axios.get(url)
const book = await res.json()
return props: book
API 端点如下所示:
import Book from '../../../models/Book';
import dbConnect from '../../../utils/dbConnect';
// conects to the database
dbConnect();
// This gets all the book from the database
export default async (req, res) =>
const books = await Book.find()
res.status(200).json(books)
我们将不胜感激任何支持或反馈。一旦我完成这项工作,我希望能够理解并帮助其他人使用 NextJs 创建动态路由。谢谢。
【问题讨论】:
这是函数getStaticPaths
中的拼写错误“$baseUrl/api/books/books
”还是正确的端点?从错误看来,路由参数id
设置不正确。您可以在控制台中记录books
的值并验证您获取的数据是否正确吗?
正如您所说,Mongo 文档包含一个_id
字段,但是当您映射books
响应时,您使用的是books.id
。那可能是你的问题。请改用books._id
。此外,始终信守诺言。由于您使用的是 async/await,因此请使用 try/catch 块。
【参考方案1】:
您不能在 getStaticProps
或 getStaticPaths
内调用 Next.js API 路由。这些函数在构建时执行,因此没有服务器正在运行来处理请求。您需要直接向 DB 提出请求。
如果你想保持干净,你可以创建一个像 allBooksIds()
这样的帮助模块,并将数据库查询保存在一个单独的文件中。
查看相同的问题 - API call in NextJS getStaticProps
【讨论】:
感谢 Nikolai 提供的信息!我现在明白我不应该从 getStaticProps 获取 API 路由,而是学习如何直接在 getStaticProps 中编写服务器端代码。我发现 NextJS Github 有很好的 mongo-mongoose 示例。感谢您的帮助。 @Nikolai:我遇到了类似的问题并得到了您的回答。我不知道,如果我理解错误,但在 Next.js 文档中有一些示例,其中 API 调用是在 getStaticPaths (nextjs.org/docs/basic-features/…) 中进行的。你能告诉我区别在哪里吗? 好的,我认为不同之处在于,在示例中他们进行了外部 api 调用。但是,也许你可以添加一个小例子来解决这个问题?会很有帮助的! @NikolaiKiselev 请看这个线程。我在这里遇到了一些奇怪的问题***.com/questions/67624322/…【参考方案2】:只需在 getStaticPaths 中添加 toString() 方法,因为书籍 ID 的类型为 ObjectID("ID"),如果您执行 params: id: book._id.toString()
,它会将 ObjectID("ID") 转换为 getStaticPaths() 接受的字符串类型。 nextjs 部分的完整代码如下,还更新了您的 API 路由,如下所示:-
上面是API路由,下面是Nextjs Page
import Book from '../../../models/Book';
import dbConnect from '../../../utils/dbConnect';
// conects to the database
dbConnect();
// This gets all the book from the database
export default async (req, res) =>
const books = await Book.find()
res.status(200).json(books)
export default function Book( book )
return (
<article>
<h1>Book Details Page</h1>
<p>book.title</p>
<p>book.author</p>
</article>
)
export async function getStaticPaths()
const url = `$baseUrl/api/books/books`
const response = await axios.get(url);
const books = response.data
const paths = books.map((book) => (
params: id: book._id.toString() ,
))
return paths, fallback: false
export async function getStaticProps( params )
const url = `$baseUrl/api/books/books/$params.id`
const res = await axios.get(url)
const book = await res.json()
return props: book
希望对你有帮助
【讨论】:
以上是关于在 NextJS 中使用“getStaticPaths”和“getStaticProps”创建动态路由的主要内容,如果未能解决你的问题,请参考以下文章
NextJS - 无法在 Tailwind CSS 中使用自定义颜色
如何在客户端 NextJS 中使用 Apollo GraphQL 订阅?
如何在 Storybook 中使用 NextJS 的 'useRouter()' 钩子