Next.js 刷新页面后无法获取数据

Cannot fetch data after refreshing the page in Next.js

我正在尝试使用从后端获取的数据创建一个简单的 Next.js 页面。为了获取,我正在使用 useSWR。

如果我在 运行 开发后第一次刷新页面或打开它,我会收到 TypeScript 错误,因为 data.results(获取的对象的数据)对象未定义。这让我相信 API 不工作或获取功能配置错误。然而这两者都不是。

如果我评论包含获取对象的 2 行 (data.results),并从浏览器刷新,我会看到一个空白页面,这并不奇怪。在那之后,如果我取消评论 console.log(data.results[1].name) 并保存更改 我可以在浏览器控制台中看到产品名称。第二次提到 data.results 也是如此。很明显,数据获取是有效的,因为我可以在某些情况下看到数据。在这种状态下,如果我点击主页按钮,然后点击主页中的Prods按钮返回,它仍然有效。它在控制台和页面中显示数据。所以只要我不刷新页面它就可以工作。

之后(不注释这两行),如果我从浏览器刷新页面,我会再次收到 TypeError。

在使用 useSWR 之前,我尝试使用 useEffect 和 useState 来达到相同的目的,但同样的事情发生了。我也使用了公理但没有任何改变。总之,无论我多么努力,我都无法使用从后端获取的内容创建一个简单的页面。我觉得我缺少一个基础知识。在问这个问题之前,我浏览了几页文档,但什么也没有。

在下面的代码中,我尝试呈现一个主页按钮和第二个产品的名称。我在上面提到的使用 data.results 的两行附近有评论。在 index.js 中只有一个链接到此产品页面的按钮。

import React, { useEffect, useState } from 'react';
import useSWR from 'swr'
import Link from "next/link"
import {Button} from '@mantine/core';

const fetcher = async (url, headers) => await fetch(url, {'method': 'GET', headers}).then(res => res.json())
function Prods() {
  const product_url = 'http://127.0.0.1:8000/api/product/'
  const headers = {
          'Content-type': 'application/json',
          'Authorization': `Token 9824eda0dd38b631b4aedf192899651cba91be53`
        }
  const { data, error } = useSWR([product_url, headers], fetcher)

  console.log(data.results[1].name) //if commented, refreshed and then uncommented it works.
  return (
    <div>
      <Link href="/" passHref>
        <Button className = "m-1">
          Homepage
        </Button>
      </Link>
      {/* {data.results[1].name} //if commented, refreshed and then uncommented it works. */}
    </div>
  )
}

export default Prods

您是否为此尝试过服务器端渲染?如果您从后端获取数据,getServerSideProps 是在 Next 应用程序中执行此操作的正确位置。

import { GetServerSideProps } from "next";

...

export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const fetcher = async (url, headers) => await fetch(url, {'method': 'GET', headers}).then(res => res.json())

  const product_url = 'http://127.0.0.1:8000/api/product/'
  const headers = {
          'Content-type': 'application/json',
          'Authorization': `Token 9824eda0dd38b631b4aedf192899651cba91be53`
        }
  const { data, error } = useSWR([product_url, headers], fetcher)
  console.log(data.results[1].name)

  return {
    props: {}
  }
}

export default Prods

您不会在浏览器的控制台选项卡上看到控制台输出,而是查看您的 IDE 终端。

或者,我会像下面那样做

import useSWR from 'swr'
import Link from "next/link"
import {Button} from '@mantine/core';

function Prods() {
  const fetcher = async (url, headers) => await fetch(url, {'method': 'GET', headers}).then(res => res.json())
  const product_url = 'http://127.0.0.1:8000/api/product/'
  const headers = {
          'Content-type': 'application/json',
          'Authorization': `Token 9824eda0dd38b631b4aedf192899651cba91be53`
  const { data, error } = useSWR([product_url, headers], fetcher)

  if (error) {
    return(<p>Loading failed...</p>);
  }

  if (!data) {
    return(<h1>Loading...</h1>);
  }

  return (
    <div>
      <Link href="/" passHref>
      <Button className = "m-1">
        Homepage
      </Button>
      </Link>
      {data.results[1].name}
    </div>
  );
}

export default Prods

import useSWR from 'swr'
import Link from "next/link"
import {Button} from '@mantine/core';

function Prods() {
  const fetcher = async (url, headers) => await fetch(url, {'method': 'GET', headers}).then(res => res.json())
  const product_url = 'http://127.0.0.1:8000/api/product/'
  const headers = {
          'Content-type': 'application/json',
          'Authorization': `Token 9824eda0dd38b631b4aedf192899651cba91be53`
  const { data, error } = useSWR([product_url, headers], fetcher)

  let pageContent;

  if (error) {
    pageContent = (<p>Loading failed...</p>);
  }
  else if (!data) {
    pageContent = (<h1>Loading...</h1>);
  }
  else {
    pageContent = (<p>data.results[1].name</p>);
  }

  return (
    <div>
      <Link href="/" passHref>
      <Button className = "m-1">
        Homepage
      </Button>
      </Link>
      {pageContent}
    </div>
  );
}

export default Prods