reactjs - 使用 NextJS 和 Material UI React 从 API 获取数据
问题描述
我正在尝试创建动态页面,根据每本书的“id”查询字符串在单独的页面上显示单个书籍的详细信息(即标题/作者等)。但是,我很难理解如何使用 NextJS 向 API 端点发出请求,该端点将根据其"id"获取书籍详细信息。我想使用 Material UI 作为 UI 框架。
问题:当我运行npm run dev
书籍页面加载但书籍的“道具”没有传递给BookAttributes
组件时。console.log(book)
我在书页中添加的是并且undefined
inconsole.log(title)
也是BookAttributes
未定义的。
- 我已经在 POSTMAN 中测试了 API 端点,它似乎可以工作。
- 当我使用 Semantic UI-React 而不是 Material UI 重构相同的代码时,书页正确加载。
- 我使用 Material UI 网站上的 NextJS Material UI 起始模板作为基线。
我对 NextJS 和 Material UI 还很陌生,因此非常感谢您的帮助和指导。感谢您对此的帮助!
这是我的代码。我试图保持干净和简单。
书页(在“页面”目录中)
import axios from 'axios';
import BookAttributes from '../components/Book/BookAttributes';
function Book({ book }) {
console.log(book)
return (
<>
<h1>Book Page</h1>
<BookAttributes {...book} />
</>
)
}
Book.getInitalProps = async ({ query: { _id } }) => {
const url = 'http://localhost:3000/api/book';
const payload = { params: { _id }}
const response = await axios.get(url, payload)
return { book: response.data }
}
export default Book;
BOOK API ENDPOINT(在“pages/api”目录中)
import Book from '../../models/Book';
import connectDb from '../../utils/connectDb';
connectDb()
export default async (req, res) => {
const { _id } = req.query
const book = await Book.findOne({ _id })
res.status(200).json(book);
}
BOOK ATTRIBUTE COMPONENT(在“组件”目录中)
import React from 'react';
function BookAttributes({ title }) {
console.log(title)
return (
<>
<h1>{title}</h1>
</>
)
}
export default BookAttributes;
解决方案
getStaticProps
如果您想使用诸如or之类的数据获取方法,您应该在此处使用动态路由getServerSideProps
。
您可以创建一个类似的页面pages/book/[id].js
。但是要生成页面,您必须决定要运行哪种数据获取方法。如果页面的数据不经常更改,您可以选择使用静态站点生成,getStaticProps
这将在构建时生成页面。如果数据将发生很大变化,您可以使用getServerSideProps
或获取数据客户端进行服务器端渲染。
这是您的用例示例,您可以将其用于服务器端渲染 using getServerSideProps
,请记住,内部的 API 调用getServerSideProps
可能会失败,因此您应该进行适当的错误处理。
在pages/book/[id].js
import axios from 'axios';
import BookAttributes from '../components/Book/BookAttributes';
export const getServerSideProps = async (ctx) => {
const bookId = ctx.params?.id
const url = 'http://localhost:3000/api/book';
const response = await axios.get(url, { params: { _id: bookId} })
return {
props: {
book: response.data
}
}
}
function Book({ book }) {
return (
<>
<h1>Book Page</h1>
<BookAttributes {...book} />
</>
)
}
export default Book;
使用 static-site-generation
因为页面是动态的,你必须提供一个路径列表,nextjs 将为其生成页面。您可以通过导出一个名为getStaticPaths
.
在pages/book/[id].js
import axios from 'axios';
import BookAttributes from '../components/Book/BookAttributes';
export const getStaticPaths = async () => {
// here you have two options if you know all the ids of the books
// you can fetch that data from the api and use all the ids to generate
// a list of paths or show a fallback version of page if you don't know all
// ids and still want the page to be static
// Pseudo code might look like this
const res = await axios.get('api-endpoint-to-fetch-all-the-books')
const paths = res.data.map(book => ({ params: { id: book.id }}))
return {
paths,
fallback: false
}
}
export const getStaticProps = async (ctx) => {
const bookId = ctx.params?.id
const url = 'http://localhost:3000/api/book';
const response = await axios.get(url, { params: { _id: bookId} })
return {
props: {
book: response.data
}
}
}
function Book({ book }) {
return (
<>
<h1>Book Page</h1>
<BookAttributes {...book} />
</>
)
}
export default Book;
fallback
的返回值中的属性理解getStaticPaths
起来有些重要。如果您知道id
页面的所有必要信息,您可以将其设置fallback
为false
. 在这种情况下,nextjs 将简单地404
为函数未返回的所有路径显示一个错误页面getStaticPaths
。
如果fallback
设置为true
nextjs 将显示页面的后备版本,而不是404
未从getStaticPaths
函数返回的路径的页面。现在你应该在哪里设置fallback
为true?假设在您的情况下,经常将新书添加到数据库中,但书籍的数据不会经常更改,因此您希望页面是静态的。在这种情况下,您可以设置fallback
并true
生成基于可用书籍 ID 的路径列表。对于新书,nextjs 将首先显示页面的后备版本,然后根据请求中提供的 id 获取数据,并将数据作为 JSON 发送,该数据将用于在客户端呈现页面。
推荐阅读
- php - 使用变量作为数组 id
- php - 在 Show Blade 中显示多对多
- node.js - 修改 Get 方法以使用 Name 获取数据
- html - 嵌套元素不以兄弟为中心
- python - 合并重叠的矩形,比较两个矩形的重叠并用边界矩形替换两者
- botframework - 我可以将信息从网页传递到 Bot Framework 网络聊天吗
- git - Katalon Studio:git 将 repo 克隆到 KS 会导致我的测试被删除
- c++ - 打包 OpenCV Dll 以分发 C++ DLL
- node.js - 找不到 vrrp_instance VI_1 的接口 eth0
- html - 多选器批量重命名加号