Не удается получить данные после обновления страницы в Next.js

Я пытаюсь создать простую страницу Next.js с данными, полученными из бэкэнда. Для получения я использую useSWR.

Если я обновляю страницу или открываю ее в первый раз после запуска dev, я получаю ошибку TypeScript, потому что объект data.results (данные извлеченного объекта) не определен. Это навело меня на мысль, что либо API не работает, либо неправильно настроены функции выборки. И все же это не так.

Если я прокомментирую две строки с извлеченным объектом (data.results) и обновлю их в браузере, я увижу пустую страницу, никаких сюрпризов. После этого момента, если я раскомментирую console.log(data.results[1].name) и сохраните изменения. Я вижу название продукта в консоли браузера. То же самое касается второго упоминания data.results. Очевидно, что выборка данных работает, потому что я могу видеть данные в некоторых ситуациях. В этом состоянии, если я нажму кнопку домашней страницы, а затем нажму кнопку Prods на домашней странице, чтобы вернуться, она все равно будет работать. Он показывает данные в консоли, а также на странице. Так что пока я не обновляю страницу, она работает.

И после этого (не комментируя эти 2 строки), если я обновляю страницу из браузера, я снова получаю TypeError.

Скриншот ошибки TypeScript

До использования SWR я пробовал использовать useEffect и useState для той же цели, но произошло то же самое. Я также использовал аксиому, но ничего не изменилось. В заключение, я не могу создать простую страницу с содержимым, полученным из бэкэнда, как бы я ни старался. Я чувствую, что мне не хватает фундаментальных знаний. Прежде чем задать этот вопрос, я просмотрел страницы документации, но ничего.

В приведенном ниже коде я пытаюсь отобразить кнопку на главной странице и название второго продукта. У меня есть комментарии рядом с двумя строками, которые я упомянул выше, которые используют data.results. В index.js есть только кнопка, которая ведет на эту страницу Prods.

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
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
0
0
31
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы пробовали рендеринг на стороне сервера для этой цели? Если вы извлекаете данные из серверной части, 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

Спасибо за помощь. Интересно, что только строки кода для исправления ошибки были: if(error) { return(<p>Loading failed...</p>);} if (!data) { return(<h1>Loading...</h1>);}. Я пробовал все альтернативы, которые вы упомянули, и все они работали, пока я не удалил эти операторы if. Я не уверен, почему это не работает, если я не проверяю данные с помощью этих ifs, но с ними это точно работает.

Yasir Aydın 10.04.2022 09:45

Страница обрабатывается до того, как данные будут готовы, и выдает ошибку. Используя эти ifs, мы гарантируем, что не попытаемся отобразить данные, связанные с API, до того, как они будут готовы.

Ahmet Firat Keler 10.04.2022 11:15

Другие вопросы по теме