具有自己查询的 Gatsby 可重用组件

Gatsby reusable components with own query

目前是否可以在 Gatsby 中构建具有自己的 graphql 查询的可重用组件?如果不是,目前将数据传递给可重用组件的最少 "coupled" 方法是什么?我似乎找不到任何执行此操作的示例,而且我在文档中也找不到任何内容。

例如,您想为博客制作一个标签云组件,该组件将显示在所有 "post" 页面的侧边栏以及单个“/tag-cloud”页面上.您可以使用 <TagCloud limit={20} /><TagCloud tags={uniqueTags} />。为此,您将需要查询所有边,map-reduce/extract 每个 tags 数组直到一组唯一的、有序的唯一标记字符串。

或者,假设您想要一个 "other products" 组件用于排除当前产品的目录页面。在这里,您可能有 <ProductsList exclude={currentProduct} />。这将是构建时的直接过滤查询。

我能看到的唯一方法是对 createPages() 的查询结果进行猴子修补,或者通过 createPage({path, component, context}) 中的 context 传递数据。这应该发生在 gatsby-node.js 吗?还有其他方法吗?

我正在回答我自己的问题。如果有人有更好的解决方案,请提交,我很乐意采纳。

我在我的问题中引用了我当前的解决方案,我认为这是次优的,它是在 pages/index.js(或您使用 [=13= 的任何地方)中构建顶级可重用组件所需的所有数据] 并将数据注入 context。这使得 component 构造函数可以通过 pathContext 属性 使用它。pathContext 这个名字让我觉得这是滥用此对象的精神,但它完成了工作。

例如,如果您有一个博客,其条目可能包含一组标签,这可能是您的 gatsby-node.js:

const path = require('path');

const getUniqueTags = edges => {
    const set = new Set();

    edges.forEach(edge => edge.node.frontmatter.tags.forEach(tag => set.add(tag)));

    return [...set];
};

exports.createPages = ({ graphql, boundActionCreators }) => resolve(graphql(`
        query AllPagesQuery {
            allMarkdownRemark {
                edges {
                    node {
                        frontmatter {
                            path
                            tags
                        }
                    }
                }
            }
        }
    `)))
    .then(({ errors, data }) => {
        const { createPage } = boundActionCreators;
        const pageTemplate = path.resolve('./src/templates/page.js');

        if (errors) return Promise.reject(errors);

        return data.allMarkdownRemark.edges.forEach(edge => {
            createPage({
                path: edge.node.frontmatter.path,
                component: pageTemplate,
                context: {
                    path: edge.node.frontmatter.path,
                    tags: getUniqueTags(data.allMarkdownRemark.edges)
                }
            });
        });
    })
    .catch(err => console.log(err));

然后您的 templates/page.js 可以像这样接收唯一标签数组:

const IndexPage = ({ pathContext }) => {
    const { tags } = pathContext.map(tag => <li>{ tag }</li>);

    return <div>{ tags }</div>;
};

export default IndexPage;

您可以在 layouts/index.js

中创建片段查询
export const avatarsFragmentQuery = graphql`
  fragment avatars on RootQueryType {
    avatars: allImageSharp {
      edges {
        node {
           id

         }
       }
    }
  }
`

并在您的页面中使用它:

export const pageQuery = graphql`
  query BlogQuery {
    site {
      siteMetadata {
        title
      }
    }

    ...avatars
  }
`