我有一个menu.js组件,我将其导入页面以生成文章列表,可以按类别对其进行过滤。效果很好。
现在,我想更改组件,以便可以按标签过滤文章。问题在于标签是graphql中的嵌套数组,我无法使用映射类别的相同map()函数来访问。
我试图做一个嵌套的map函数,但是我无法使其工作,但是我怀疑这是解决方案。我的目标是拥有相同的功能,使我可以按标签而不是按类别过滤文章。我希望那是可能的。我正在使用带有Strapi后端的盖茨比。朝正确方向的任何提示表示赞赏:-)
/src/pages/articles.js
import graphql from 'gatsby'
import React from 'react'
import Layout from 'components/layout'
import MenuBlog from 'components/menublog'
const BlogPage = ({ data }) => (
<Layout>
<MenuBlog items={data.menu} />
</Layout>
)
export default BlogPage
export const pageQuery = graphql`
query BlogQuery {
menu: allStrapiArticle {
edges {
node {
id
title
slug
tag {
title
id
}
category {
title
id
}
}
}
}
}
`
这是我从上面的GraphQL查询中得到的结果,每篇文章当然可以具有一个或多个标签,但只能分配一个类别
{
"data": {
"menu": {
"edges": [
{
"node": {
"title": "articleName 1",
"slug": "articleName-1",
"category": {
"title": "cat1"
},
"tag": [
{
"title": "tag1"
},
{
"title": "tag2"
},
{
"title": "tag3"
}
]
}
},
{
"node": {
"title": "articleName 2",
"slug": "articleName-2",
"category": {
"title": "cat2"
},
"tag": [
{
"title": "tag3"
}
]
}
}
]
}
}
}
这是我的组件,用于根据所选类别显示文章
/src/components/menublog/index.js
import React, { Component } from 'react'
import { Link } from 'gatsby'
import Row from 'react-bootstrap/Row'
const getCategories = items => {
let tempItems = items.map(items => {
return items.node.category.title
})
let tempCategories = new Set(tempItems)
let categories = Array.from(tempCategories)
categories = ['all', ...categories]
return categories
}
export default class MenuBlog extends Component {
constructor(props) {
super(props)
this.state = {
items: props.items.edges,
articles: props.items.edges,
categories: getCategories(props.items.edges),
}
}
handleItems = category => {
let tempItems = [...this.state.items]
if (category === 'all') {
this.setState(() => {
return { articles: tempItems }
})
} else {
let items = tempItems.filter(
({ node }) => node.category.title === category
)
this.setState(() => {
return { articles: items }
})
}
}
render() {
if (this.state.items.length > 0) {
return (
<Row>
{/* items */}
<div className="col-md-8 blog-main bg-light">
<h1>Artikler</h1>
{this.state.articles.map(({ node }) => {
return (
<div key={node.id} className="blog-post mb-4">
<h2>
<Link to={`/artikler/${node.slug}`}>{node.title}</Link>
</h2>
{/* item text */}
</div>
)
})}
</div>
{/* categories */}
<div className="col-md-4 blog-sidebar">
<div className="p-4 mb-3 bg-light">
<h4>Kategorier</h4>
<ol className="list-unstyled mb-0">
{this.state.categories.map((category, index) => {
return (
<li key={index}>
<button
type="button"
className="btn"
onClick={() => {
this.handleItems(category)
}}
>
{category}
</button>
</li>
)
})}
</ol>
</div>
<div className="p-4 mb-3 bg-light">
<h4>Kategorier</h4>
</div>
</div>
</Row>
)
} else {
return <h1>no items</h1>
}
}
}
答案 0 :(得分:1)
您应该可以使用类似于类别方法的内容:
items = tempItems.filter(({ node }) =>
node.tag.map(tag => tag.title).includes("tag2")
);
由于这不一定是特定于React / Gatsby的,因此这里只是数据和这些方法:
const data = {
data: {
menu: {
edges: [{
node: {
title: "articleName 1",
slug: "articleName-1",
category: {
title: "cat1"
},
tag: [{
title: "tag1"
},
{
title: "tag2"
},
{
title: "tag3"
}
]
}
},
{
node: {
title: "articleName 2",
slug: "articleName-2",
category: {
title: "cat2"
},
tag: [{
title: "tag3"
}]
}
}
]
}
}
};
let items = data.data.menu.edges.filter(
({
node
}) => node.category.title === "cat2"
);
console.log(items);
items = data.data.menu.edges.filter(({
node
}) =>
node.tag.map(tag => tag.title).includes("tag2")
);
console.log(items);