【问题标题】:I am unable to create pages dynamically using Gatsby我无法使用 Gatsby 动态创建页面
【发布时间】:2020-10-23 06:40:44
【问题描述】:

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

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

我对@9​​87654325@ 有多个查询:

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,
        },
      })
    })
})

这是我的 React 组件:

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 界面上运行这些精确查询,一切都会完美运行:

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

【问题讨论】:

    标签: javascript reactjs ecmascript-6 graphql gatsby


    【解决方案1】:

    您必须在 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 Schema and Types的信息。

    【讨论】:

      【解决方案2】:

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

      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
      

      【讨论】:

        猜你喜欢
        • 2021-07-02
        • 1970-01-01
        • 2020-04-03
        • 2020-07-25
        • 2021-02-08
        • 2012-03-25
        • 2015-10-30
        • 1970-01-01
        • 2021-11-03
        相关资源
        最近更新 更多