【问题标题】:Limit filtered Graphql items in Gatsby.js在 Gatsby.js 中限制过滤的 Graphql 项目
【发布时间】:2021-02-03 23:25:41
【问题描述】:

所以我正在尝试对我的投资组合项目进行过滤引导导航药片,类似于:

每当点击特定类别时,它只会显示该类别下的那些项目。但是这一次有一个转折,因为我需要限制每页 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 个关于分页和过滤项目组合的查询可以做到这一点。有谁能帮我用 sn-ps 解决这个问题吗?

提前致谢!

【问题讨论】:

    标签: javascript twitter-bootstrap graphql gatsby strapi


    【解决方案1】:

    您的问题出现是因为您有两个具有相同名称的查询,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
                            }
                        }
                    }
                }
            }
        }
    `
    

    您可以找到aliasing queries in GraphQL docs的更多详细信息。

    【讨论】:

    • 194:3 错误此匿名操作必须是唯一定义的操作
    • 已更新。第二个查询必须包含在里面以避免变异问题。
    • 也没有用。我觉得我的逻辑有问题。
    猜你喜欢
    • 2022-12-30
    • 2019-10-01
    • 2018-07-09
    • 2021-10-02
    • 2020-09-11
    • 2019-02-20
    • 2021-05-28
    • 2019-06-25
    • 2019-06-18
    相关资源
    最近更新 更多