【问题标题】:How to map nested array in gatsby with reactjs and graphql如何使用 reactjs 和 graphql 在 gatsby 中映射嵌套数组
【发布时间】:2020-01-16 07:48:42
【问题描述】:

我有一个组件 menu.js,我将其导入页面以生成可以按类别过滤的文章列表。这完美无缺。

现在我想更改组件,以便我可以按标签过滤文章。问题是标签是 graphql 中的嵌套数组,我无法使用映射类别的相同 map() 函数来访问它。

我试图做一个嵌套的地图功能,但我不能让它工作,但我怀疑这是解决方案。我的目标是拥有相同的功能,我可以按标签而不是按类别过滤文章。我希望那是可能的。我正在使用带有 Strapi 后端的 gatsby。任何正确方向的提示表示赞赏:-)

/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>
    }
  }
}

【问题讨论】:

    标签: arrays reactjs graphql gatsby strapi


    【解决方案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);

    【讨论】:

      猜你喜欢
      • 2021-02-14
      • 2020-03-06
      • 2017-05-14
      • 2013-07-17
      • 1970-01-01
      • 1970-01-01
      • 2021-03-18
      • 1970-01-01
      • 2023-01-18
      相关资源
      最近更新 更多