Получение данных из API с использованием Next JS и Material UI React - PullRequest
0 голосов
/ 18 июня 2020

Я пытаюсь создать динамические c страницы, которые отображают отдельные детали книги (например, название / автор и c) на отдельной странице на основе строки запроса "id" каждого книга. Однако мне сложно понять, как сделать запрос к конечной точке API с помощью Next JS, который получит сведения о книге на основе его «id» . Я хотел бы использовать Material UI в качестве UI Framework.

ПРОБЛЕМА : когда я запускаю npm run dev, страница книги загружается, но «реквизиты» книги не передаются в BookAttributes компонент. console.log(book), который я добавил на страницу книги, - это undefined, а console.log(title) в BookAttributes также не определен.

  1. Я протестировал конечную точку API в POSTMAN, и, похоже, он работает.
  2. Когда я реорганизую тот же код, используя Semanti c UI-React вместо UI-материала материала, страницы книги загружаются правильно.
  3. Я использую стартовый шаблон Next JS Material UI с веб-сайта Material UI в качестве базового.

Я новичок в Next JS и Материальный интерфейс, поэтому мы будем благодарны за вашу помощь и руководство. Спасибо за вашу помощь!

Вот код у меня так. Я старался сохранить ясность и простоту.

СТРАНИЦА КНИГИ (в каталоге 'pages')

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;

КОНЕЧНАЯ ТОЧКА API КНИГИ ( в каталоге '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);
}

КОМПОНЕНТ АТРИБУТА КНИГИ (в каталоге 'components')

import React from 'react';

function BookAttributes({ title }) {

    console.log(title)

    return (
        <>
            <h1>{title}</h1>
        </>
    )
}

export default BookAttributes;

1 Ответ

0 голосов
/ 18 июня 2020

Вы должны использовать здесь динамические c маршруты, если хотите работать с такими методами выборки данных, как getStaticProps или getServerSideProps.

Вы можете создать страницу типа pages/book/[id].js. Но чтобы сгенерировать страницу, вы должны решить, какой метод выборки данных вы хотите запустить. Если данные для страницы меняются не очень часто, вы можете использовать stati c -site-generation, используя getStaticProps, который будет генерировать страницы во время сборки. Если данные будут сильно меняться, вы можете выполнить рендеринг на стороне сервера, используя getServerSideProps, или получить данные на стороне клиента.

Вот пример вашего варианта использования, который вы можете использовать для сервера -side-рендеринг с использованием getServerSideProps, имейте в виду, что вызов API внутри getServerSideProps может завершиться ошибкой, поэтому у вас должна быть соответствующая обработка ошибок.

In 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;

Использование stati c -site-generation Поскольку страница является динамической c, вы должны предоставить список путей, для которых следующая js будет генерировать страницы. Это можно сделать, экспортировав функцию asyn c с именем 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. В этом случае следующий js просто покажет страницу ошибки 404 для всех путей, которые не были возвращены функцией getStaticPaths.

Если fallback установлен на true следующий js будет отображать резервную версию страницы вместо страницы 404 для путей, которые не были возвращены функцией getStaticPaths. Где теперь установить fallback в значение true? Предположим, что в вашем случае новые книги добавляются в базу данных часто, но данные о книгах меняются не очень часто, поэтому вы хотите, чтобы страницы были статичными c. В этом случае вы можете установить fallback на true и создать список путей на основе доступных идентификаторов книг. Для новых книг следующий js сначала покажет резервную версию страницы, затем получит данные на основе идентификатора, указанного в запросе, и отправит данные как JSON, которые будут использоваться для визуализации страницы в клиенте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...