如何在最新的 Next.js 中获取服务器端数据?尝试了 getStaticProps,但它没有运行并且未定义

How to fetch data server-side in the latest Next.js? Tried getStaticProps but it's not running and getting undefined

提问人:victor 提问时间:5/17/2023 最后编辑:Youssouf Oumarvictor 更新时间:8/31/2023 访问量:7639

问:

我正在使用 Next.js 开发 Django Rest 框架,并且我无法从 API 获取数据。我在这个 url 中有数据,当我访问该 url 时,我会看到数据。http://127.0.0.1:8000/api/campaigns

问题是当我使用 Next.js 获取和控制台数据时,我得到 .此外,当我尝试映射数据时,出现错误:undefined

未处理的运行时错误

错误:无法读取未定义的属性(读取“map”)

这是我完成数据获取的文件:Index.js

import React from 'react'

export default function Index ({data}) {
  console.log(data)
  return (
    <div>
      <main>
        <h1>Available Campaigns</h1>
        {data.map((element) => <div key={element.slug}>
          <div>
            <div>
              <img src={element.logo} height={120} width={100} alt="image" />
            </div>
            <div></div>
          </div>

        </div>)}
      </main>
    </div>
  );
}

export async function getStaticProps() {
  const response = await fetch("http://127.0.0.1:8000/api/campaigns");
  const data = await response.json();
  return {
    props: {
      data: data
    },
  }
}

这是我访问URL时获得的数据的屏幕截图:

Image

下面是前端内 Next.js 应用的文件结构:

File Structure

另外,请注意,我使用的是最新版本的Next.js。任何帮助将不胜感激。谢谢。

JavaScript ReactJS Django REST 下一个.js

评论

0赞 Yilmaz 5/17/2023
你在这里得到什么const data = await response.json(); console.log(data)
0赞 Youssouf Oumar 5/17/2023
你能展示一下你的文件结构吗?您显示的组件在您的文件夹中的什么位置?
0赞 victor 5/17/2023
@Yilmaz不返回任何内容console.log(data)
0赞 victor 5/17/2023
@YoussoufOumar我刚刚编辑了它并添加了屏幕截图。谢谢

答:

14赞 Youssouf Oumar 5/17/2023 #1

像 getServerSidePropsgetStaticProps 这样的方法用于在服务器上获取数据,但它们仅适用于 pages 文件夹中的页面组件(在 Next.js 中设置路由的初始方法)。

从 Next.js 13 开始,在应用程序目录中(当您对下图中显示的最后一个问题回答“是”时使用)中,我们有服务器组件,您可以在其中直接在组件主体中获取数据,如以下代码片段所示(请阅读注释):

enter image description here

/*
  If you want to access headers or cookies while fetching data,
  you can use these functions:
*/
import { cookies, headers } from "next/headers";

/*
 If the below component is the default export of a `page.js` and you are using 
 dynamic routes, slugs will be passed as part of `params`, and 
 query strings are passed as part of `searchParams`.
*/
export default async function Component({ params, searchParams }) {
  /* 
    This request should be cached until manually invalidated.
    Similar to `getStaticProps`.
    `force-cache` is the default and can be omitted.
  */
  const staticData = await fetch(`https://...`, { cache: "force-cache" });

  /*
    This request should be refetched on every request.
    Similar to `getServerSideProps`.
  */
  const dynamicData = await fetch(`https://...`, { cache: "no-store" });

  /* 
    This request should be cached with a lifetime of 10 seconds.
    Similar to `getStaticProps` with the `revalidate` option.
  */
  const revalidatedData = await fetch(`https://...`, {
    next: { revalidate: 10 },
  });

  return "...";
}

话虽如此,您可以在不使用任何库的情况下获取数据,甚至可以使用 ORM 直接与数据库通信,在这种情况下,您可以使用路由段配置fetch()

// layout.js OR page.js OR route.js 👈🏽

import prisma from "./lib/prisma";

/*
  Keep one of the possibilities shown below (there are more on the doc), 
  depending on your needs. 
*/

export const revalidate = 10; // If you want to revalidate every 10s
// OR
export const dynamic = "force-dynamic"; // If you want no caching at all
// ...

async function getPosts() {
  const posts = await prisma.post.findMany();
  return posts;
}

export default async function Page() {
  const posts = await getPosts();
  // ...
}

评论

0赞 Sebak Thapa 8/17/2023
我们应该如何从使用异步函数(使用 SSG 的新方法)获取的数据中管理全局状态?
0赞 Youssouf Oumar 8/17/2023
嗨,塞巴克!这个线程中的答案就是这样。
2赞 Ahsan Khan 6/12/2023 #2

在应用程序目录中,您不能使用 、 等方法获取数据。与服务器组件相反,您可以使组件自异步并直接在组件主体中获取数据。此外,您可以将数据传递给客户端组件以提供服务。getServerSidePropsgetStaticPropsgetInitialProps

export async function getData(){
 const res = await fetchData();
 const data = res.json()
 
return data
}

现在,您可以在主组件中调用此异步函数

export async function(){
   const data = await getData()
   return (<ClientComponent data />)
}

评论

0赞 Sebak Thapa 8/17/2023
我们如何管理使用 SSG 或 SSR 获取的数据的全局状态?
5赞 Joshua Dance 7/26/2023 #3

此 StackOverFlow 问题(无法在 Next.js 13 中使用 GetStaticProp)已作为此问题的重复项关闭。

为了帮助像我这样的新手:

您不能在 Nextjs 13 中使用 getStaticProps(使用 App Router)。

新的方法是只使用 fetch。您可以在此处阅读有关 fetch 的更多信息。

async function getArtist(username: string) {
  const res = await fetch(`https://api.example.com/artist/${username}`)
  return res.json()
}

这张图片比较了新旧做事方式。图片来源

enter image description here

由于新的默认值是缓存所有 fetch 请求(除非它们选择退出),因此在静态组件中调用 fetch 具有与 相同的效果。您可以在此处阅读有关静态数据获取的更多信息。getStaticProps

因此,要明确这个正常的获取请求:

//Similar to 'getStaticProps' when used in a static rendering component
fetch(API_URL)

与此“force-cache”请求相同:

//This request would be cached until manually invalidated. 
//Similar to 'getStaticProps'
//Use this type of fetching for data that does not change often.
 
fetch(API_URL, { cache: 'force-cache' })

有关默认缓存的详细信息,请点击此处

你为什么一开始就想使用 getStaticProps?

为了帮助那些在教程中找到并在这里找到方法的新手,您想要使用的原因是您希望渲染一次页面,然后将该页面发送给每个用户。getStaticPropsgetStaticProps

这使您的页面更快,向用户发送更少的代码,并且更适合 SEO 等。

但是,如果您需要获取一些数据来呈现该页面一次,该怎么办?在 Nextjs 13 之前,您将使用 .getStaticProps

现在你在一个静态组件中。效果是一样的。fetch

这种效果是,一旦(在部署项目的构建时)Nextjs 将获取一些数据,然后使用该数据来渲染页面,然后将预渲染的页面发送给需要它的每个人。

如果需要使用动态路由静态生成一堆页面,则该函数可用于在构建时生成路由,而不是在请求时按需生成动态路由。信息在这里generateStaticParams

对于新手来说,如果你不知道什么是动态路由,就用.:)fetch

评论

1赞 Sebak Thapa 8/12/2023
从下一个开始,js 具有缓存功能。这是否意味着我们不必使用像react query这样的库?
1赞 Joshua Dance 8/15/2023
@SebakThapa 视情况而定,但你现在可能会。React Query 除了获取之外还会做其他事情,但这篇博文可能会帮助你提供更多细节 - tkdodo.eu/blog/you-might-not-need-react-query