繁体   English   中英

我无法使用 Gatsby 动态创建页面

[英]I am unable to create pages dynamically using Gatsby

我在我的项目中使用 Gatsby。 我正在尝试创建一个需要分页的页面。

我遵循了这个https://www.gatsbyjs.org/docs/adding-pagination/和这个其他指南https://nickymeuleman.netlify.app/blog/gatsby-pagination/以及如何做到这一点,但它不起作用。

我对gatsby-node.js有多个查询:

exports.createPages = async ({ graphql, actions, page }) => {
    const { createPage } = actions
    const shop = path.resolve("./src/templates/shop.js")
    const productPageTemplate = path.resolve("./src/templates/ProductPage/index.js")
    
    const singleProduct = await graphql(`
      query {
        allShopifyProduct {
          edges {
            node {
              handle
            }
          }
        }
      }
    `)
    
    // This is the query which I need for the pagination
    // Create shop pages
    const products = await graphql(`
      query allShopifyProduct($skip: Int!, $limit: Int!) {
        allShopifyProduct(sort: { fields: [createdAt], order: DESC }
          skip: $skip
          limit: 5
        ) {
          edges {
            node {
              id
              title
              handle
            }
          }
        }
      }
    `)
    
    const posts = products.data.allShopifyProduct.edges  
    
    const postsPerPage = 5
    const numPages = Math.ceil(posts.length / postsPerPage)
    
    Array.from({ length: numPages }).forEach((_, i) => {
      const withPrefix = (pageNumber) =>
        pageNumber === 1 ? `/shop` : `/shop/${pageNumber}`
      const pageNumber = i + 1
      createPage({
        path: withPrefix(pageNumber),
        component: shop,
        context: {
          limit: postsPerPage,
          skip: i * postsPerPage,
          current: pageNumber,
          total: numPages,
          hasNext: pageNumber < numPages,
          nextPath: withPrefix(pageNumber + 1),
          hasPrev: i > 0,
          prevPath: withPrefix(pageNumber - 1),
        },
      })
    })
    
    // Adding the single product stuff to show my multiple queries
    singleProduct.data.allShopifyProduct.edges.forEach(({ node }) => {
      createPage({
        path: `/product/${node.handle}/`,
        component: productPageTemplate,
        context: {
          // Data passed to context is available
          // in page queries as GraphQL variables.
          handle: node.handle,
        },
      })
    })
})

这是我的反应组件:

import React from "react"
import { graphql, Link } from "gatsby"

// Components
import ProductGrid from "@components/ProductGrid/productGrid"

const Shop = ({ data: { allShopifyProduct }, pageContext }) => {
  return (
    <div className="product-grid">
      <ProductGrid allShopifyProduct={allShopifyProduct}
      />
      {!pageContext.hasPrev && (
        <Link to={pageContext.prevPage} rel="prev">
          ← Previous Page
        </Link>
      )}
      {!pageContext.hasNext && (
        <Link to={pageContext.nextPage} rel="next">
          Next Page →
        </Link>
      )}
    </div>
  )
}

export default Shop

export const query = graphql`
  query allShopifyProduct($skip: Int!, $limit: Int!) {
    allShopifyProduct(
      sort: { fields: [createdAt], order: DESC }
      skip: $skip
      limit: $limit
    ) {
      edges {
        node {
          id
          title
          handle
        }
      }
    }
  }
`

它不断抛出如下错误:

 ERROR #85927  GRAPHQL

There was an error in your GraphQL query:

Variable "$skip" is never used in operation "allShopifyProduct".

See if $skip has a typo or allShopifyProduct doesn't actually require this variable.

File: gatsby-node.js:74:26


 ERROR #85927  GRAPHQL

There was an error in your GraphQL query:

Variable "$limit" is never used in operation "allShopifyProduct".

See if $limit has a typo or allShopifyProduct doesn't actually require this variable.

File: gatsby-node.js:74:26


 ERROR #11321  PLUGIN

"gatsby-node.js" threw an error while running the createPages lifecycle:

Cannot read property 'allShopifyProduct' of undefined

  108 |   `)
  109 |
> 110 |   const posts = products.data.allShopifyProduct.edges
      |                               ^
  111 |

File: gatsby-node.js:110:31



  TypeError: Cannot read property 'allShopifyProduct' of undefined

  - gatsby-node.js:110 Object.exports.createPages
    /Users/marcelo/Work/gatsby-on-demand/gatsby-node.js:110:31

failed createPages - 0.113s

如果我在我的 GraphiQL 界面上运行这些确切的查询,一切都会完美运行: 在此处输入图像描述

关于我在哪里失败的任何想法?

您必须在createPage API 中的上下文中提供这些变量:

  createPage({
    path: `/product/${node.handle}/`,
    component: productPageTemplate,
    context: {
      skip: 0 // or any variable
      limit: 5 // or any variable
      handle: node.handle, // is it used? If don't, you can remove it
    },
  })

由于您在查询中使用了不可为空的skiplimit变量(标有感叹号, ! ):

  query allShopifyProduct($skip: Int!, $limit: Int!)

它们需要存在,因此您需要以与您在 GraphQL 查询游乐场中出现的方式相同的方式提供它们(通过上下文)。

您的handle变量似乎未使用,至少在提供的代码中,在这种情况下,您可以将其删除。

有关GraphQL 架构和类型的更多信息。

一开始......传递查询中使用的参数/值(作为变量)的方法......您应该将它们(值)传递给“循环”查询中的变量:

let myLoopingSkip = 0; // starting skip

// Create shop pages
const products = await graphql(`
  query allShopifyProduct($skip: Int!, $limit: Int!) {
    allShopifyProduct(sort: { fields: [createdAt], order: DESC }
      skip: $skip
      limit: $limit
    ) {
      edges {
        node {
          id
          title
          handle
        }
      }
    }
  }
`,  { skip: myLoopingSkip, limit: 5 } ); // variables used in query

然后,您可以在整个(用于分页列表和单个产品的查询+createPages)块上构建一个“外部”循环,将当前myLoopingSkip值传递给查询变量skip

两种可能的循环场景

  • 一次查询所有产品(所有数据);
  • 仅查询当前迭代所需的数据段(5 项记录集/块)。

第一个选项很简单,但在大型数据集上可能会占用大量资源,它可能会在某个时刻崩溃。

第二个(恕我直言,更好)选项更可靠,但在循环之前需要额外/单独查询numPages (所有产品的数量)。 有条件的next page也需要它。

在现实生活中,在 10 页之后浏览是不寻常的......实际上,即使谷歌在某些页面限制后停止显示结果......但产品页面必须链接到某个地方才能访问/抓取 - 恕我直言,最好按类别有更短的分页列表.

如果您真的不需要numPages ,只要查询数据(结果)包含 5 条记录,您就可以通过添加 5 (您的“限制”/ postsPerPage )来保持循环。 在这种情况下,“外循环”可能如下所示:

const postsPerPage = 5;
let myLoopingSkip = 0; // starting skip
do {
  // read only data you need in current iteration
  let products = await graphql(PAGINATED_PRODUCTS_QUERY, 
    { skip: myLoopingSkip, limit: postsPerPage } );

  // paginated list
  createPage({
    path: withPrefix(pageNumber),
    component: shop,
    context: {
      limit: postsPerPage,
      skip: i * postsPerPage,
    ...      
  // but you can just pass fetched data
  // as is done for product page
  // no need for query inside component
  // just loop over `data` prop to create grid view
  //
  // createPage({
  //   path: withPrefix(pageNumber),
  //   component: shop,
  //   context: {
  //     data: products.data.allShopifyProduct.edges,

  // loop for single products pages
  products.data.allShopifyProduct.edges.map( (node) => {
    createPage({
    path: `/product/${node.handle}/`,
    component: productPageTemplate,
    context: {
      // Data passed to context is available
      // in page queries as GraphQL variables.
      handle: node.handle,
      // ... but we already have all data here 
      // ... again, no query needed
      // data: node
    }
  });

  myLoopingSkip += postsPerPage;
} while( products.data.allShopifyProduct.edges.length===postsPerPage )
// or use total page condition

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM