首页 > 解决方案 > 在 Gatsby.js 中限制过滤的 Graphql 项目

问题描述

所以我试图在我的投资组合项目上做一个过滤的 Bootstrap 导航药片,类似于:

在此处输入图像描述

每当单击特定类别时,它只会显示该类别下的那些项目。但这一次有一个转折,因为我需要限制每页 3 个项目,并且分页是固定的。

所以我所做的是我创建了 2 个 graphql 查询:

export const queryFilter = graphql`
query getAllWorks($skip: Int!, $limit: Int!){
    allStrapiWorks(
        skip: $skip, 
        limit: $limit, 
        sort: {fields: created_at, order: DESC}
      ){
        nodes {
          id
          name
          slug
          category
          stack {
            stack_name
            id
          }
          featured_image {
            childImageSharp {
              fluid {
                ...GatsbyImageSharpFluid_withWebp
              }
            }
          }
        }
      }
  }
`

export const queryAll = graphql`
  {
    allStrapiWorks{
      nodes {
        id
        name
        slug
        category
        stack {
          stack_name
          id
        }
        featured_image {
          childImageSharp {
            fluid {
              ...GatsbyImageSharpFluid_withWebp
            }
          }
        }
      }
    }
  }
`

export default Works

第一个查询将限制每页的项目选择。第二个用于过滤和显示所有类别。

这是副本gatsby-node.js

// amount of blog
const blogs = result.data.blogs.nodes
// posts per page
const blogsPerPage = 3
// how many pages
const numPages = Math.ceil(blogs.length/blogsPerPage)

Array.from({ length: numPages}).forEach((_, i) => {
  createPage({
    path: i === 0 ? `blogs` : `/blogs/${i+1}`,
    component: path.resolve('src/templates/blog-list-template.js'),
    context: {
      limit: blogsPerPage,
      skip: i * blogsPerPage,
      numPages,
      currentPage: i + 1
    }
  })
})


// amount of works
const works = result.data.works.nodes
// works per page
const worksPerPage = 3
// how many works
const numWorkPages = Math.ceil(works.length/worksPerPage)

Array.from({ length: numWorkPages}).forEach((_, i) => {
  createPage({
    path: i === 0 ? `works` : `/works/${i+1}`,
    component: path.resolve('src/templates/work-list-template.js'),
    context: {
      limit: worksPerPage,
      skip: i * worksPerPage,
      numPages,
      currentPage: i + 1
    }
  })
})

因此,在我的代码中,我得到了 2 个用于过滤和获取所有类别的外部函数:

const getAllCategories = catData => {
    let tempItems = catData.map(cat => {
        return cat.category;
    });
    
    let tempCategories = new Set(tempItems);

    let categories = Array.from(tempCategories);
    return categories;
}

const filterByCategory = (category, works) => {
    let categoryItems = works.filter(items => {
       return items.category === category;
    })
    
    return categoryItems;
}

然后在我的函数中,我调用了这两个函数,以便它只显示所有过滤的项目,但带有分页:

const Works = (props) => {

    const { currentPage, numPages } = props.pageContext

    const isFirst = currentPage === 1
    const isLast = currentPage === numPages
    
    const nextPage = `/works/${currentPage+1}`
    const prevPage = currentPage - 1 === 1 ? `/works` : `/works/${currentPage-1}`
    
    const { data } = props

    console.log('hellloo >>>>', data.allStrapiWorks.nodes)

    const dataAll = useStaticQuery(queryAll)
    const { allStrapiWorksNotFiltered: { nodes:works } } = dataAll
    const [currentCategory, setCategory] = useState('web_development')
    const allCategories = getAllCategories(works);
    const selectItemsFromCategory = filterByCategory(currentCategory, works);


 return (
     <>
    <Preloader />
    <Layout>
      <Helmet>
        <script src={withPrefix('jquery.min.js')} type="text/javascript" />
        <script src={withPrefix('navscroll.min.js')} type="text/javascript" />
        <script src={withPrefix('owl.carousel.min.js')} type="text/javascript" />
        <script src={withPrefix('sticky-menu.js')} type="text/javascript" />
        <script src={withPrefix('aos.js')} type="text/javascript" />
        <script src={withPrefix('script.js')} type="text/javascript" />
    </Helmet>
    <PageBanner title="Works"/>
 
        
        <div className="project-section section-padding">
            <div className="container container-wide">
                <div className="project-wrapper row">

                    <div className="col-lg-12 mb-30" data-aos="zoom-in">
                        <ul className="nav justify-content-center" id="categories" role="tablist">

                {
                
                allCategories.map(cat => (
                    <li className="nav-item">
                    <a aria-controls={`aria-${cat}`} 
                       aria-selected="true" 
                       onClick={() => setCategory(cat)}
                       className={`nav-link show portfolio-nav ${cat === currentCategory ? 'active' : ''}`}
                       data-toggle="tab" 
                       data-work-tab={ cat.split('_').join(' ') }
                       href={ `#${cat.split('_').join(' ')}`}
                       role="tab">
                         { cat.split('_').join(' ') }</a>
                    </li>   
                ))}

                    </ul>
                    </div>

         
                    <div className="col-lg-12">
                        <div className="tab-content" id="catsContent">
                        <div aria-labelledby="items" className="tab-pane fade show active" role="tabpanel">
                            <div className="row">
                        {  selectItemsFromCategory.map(workItem => {
                            const { id, featured_image, name, slug, stack } = workItem;
                        
                            return (

                                    <div className="project col-xl-3 col-md-6 col-12">
                                        <div className="project-inner">
                                            <div className="project-image">
                                            <Link to={`/works/${slug}`} key={id}>
                                                <Image fluid={featured_image.childImageSharp.fluid} alt={name} /> 
                                                </Link>
                                            </div>
                                            <div className="project-content">
                                                <h3 className="title text-center mb-3">
                                                 <Link to={`/works/${slug}`} key={id}>{name}</Link>
                                                 </h3>
                                                 {
                                                stack.map(stackItem => {
                                                return <span data-tag={stackItem.stack_name} key={stackItem.id}>{stackItem.stack_name}</span>
                                                })
                                                    }
                                            </div>
                                        </div>
                                    </div>
                    
                            )

                        })

                        }

                        </div>
                            </div>
                        </div>
                    </div>




                </div>
                <div className="row mt-50" data-aos="zoom-in">
                    <div class="col">
                        <ul className="pagination">
                            <li>
                                <a data-pagination="«" href="#">«</a>
                            </li>
                            <li>
                                <a class="active" data-pagination="1" href="#">1</a>
                            </li>
                            <li>
                                <a data-pagination="2" href="#">2</a>
                            </li>
                            <li>
                                <a data-pagination="3" href="#">3</a>
                            </li>
                            <li>
                                <a data-pagination="»" href="#">»</a>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>




    </Layout>
    </>

 )
}

当然,这没有用。相反,它向我抛出了错误:

Multiple "root" queries found: "getAllWorks" and "cUsersRobDesktopGatsbyTestRobPortfolioGatsbysrctemplatesworkListTemplateJs1831412216".
Only the first ("cUsersRobDesktopGatsbyTestRobPortfolioGatsbysrctemplatesworkListTemplateJs1831412216") will be registered.

Instead of:

   1 | query cUsersRobDesktopGatsbyTestRobPortfolioGatsbysrctemplatesworkListTemplateJs1831412216 {
   2 |   allStrapiWorks {
   3 |     #...
   4 |   }
   5 | }
   6 | 
   7 | query getAllWorks {
   8 |   allStrapiWorks {
   9 |     #...
  10 |   }
  11 | }

Do:

  1 | query getAllWorksAndCUsersRobDesktopGatsbyTestRobPortfolioGatsbysrctemplatesworkListTemplateJs1831412216 {
  2 |   allStrapiWorks {
  3 |     #...
  4 |   }
  5 |   allStrapiWorks {
  6 |     #...
  7 |   }
  8 | }

This can happen when you use two page/static queries in one file. Please combine those into one query.
If you're defining multiple components (each with a static query) in one file, you'll need to move each component to its own file.

File: C:/Users/Rob/Desktop/Gatsby-Test/Rob-portfolio-gatsby/src/templates/work-list-template.js

我什至不确定是否对分页和过滤项目组合进行 2 个查询会做到这一点。有谁能帮我用片段解决这个问题吗?

提前致谢!

标签: javascripttwitter-bootstrapgraphqlgatsbystrapi

解决方案


您的问题出现是因为您有两个具有相同名称的查询,allStrapiWorks其中一个没有名称。Gatsby 会在内部为每个包含路径的名称(getAllWorksAndCUsersRobDesktopGatsbyTestRobPortfolioGatsbysrctemplatesworkListTemplateJs1831412216在这种情况下)生成一个名称,并对查询本身进行哈希处理(以避免缓存问题)。由于它在完全相同的位置找到完全相同的查询,因此两次失败。

您可以做的一件简单的事情是提供一个名称(或别名)并将其放在同一个查询对象中:

   export const allQueries = graphql`
    query getAllWorks($skip: Int!, $limit: Int!){
        query1:allStrapiWorks(
            skip: $skip,
            limit: $limit,
            sort: {fields: created_at, order: DESC}
        ){
            nodes {
                id
                name
                slug
                category
                stack {
                    stack_name
                    id
                }
                featured_image {
                    childImageSharp {
                        fluid {
                            ...GatsbyImageSharpFluid_withWebp
                        }
                    }
                }
            }
        }
        
        query2:allStrapiWorks{
            nodes {
                id
                name
                slug
                category
                stack {
                    stack_name
                    id
                }
                featured_image {
                    childImageSharp {
                        fluid {
                            ...GatsbyImageSharpFluid_withWebp
                        }
                    }
                }
            }
        }
    }
`

您可以在 GraphQL 文档中找到有关别名查询的更多详细信息。


推荐阅读