javascript - 在 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 个查询会做到这一点。有谁能帮我用片段解决这个问题吗?
提前致谢!
解决方案
您的问题出现是因为您有两个具有相同名称的查询,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 文档中找到有关别名查询的更多详细信息。
推荐阅读
- git - 推送到 github 时 Git 未使用正确的 SSH 密钥
- linux - 如何删除或替换 VIM 中的单词
- css - 如何在列表项标记处于活动状态时更改它
- git - Git 将多个分支合并到 master 分支,即使一个分支没有与 master 分支
- html - Bootstrap 4 Carousel Fullscreen 当'PageWrap'(容器)宽度:1140px
- linux - 使用 plink.exe 时如何获取 ls 命令以在列中输出结果
- python - 如何在 appache 气流会话中检查连接是否建立
- pentaho - 工作中不同参数的相同转换
- c# - 从复选框覆盖 GetItemCheckState()
- python - 使用 if 检查用户输入时未定义的变量