4

Gatsby 目前是否可以构建具有自己的 graphql 查询的可重用组件?如果不是,那么目前将数据传递给可重用组件的最“耦合”方式是什么?我似乎找不到任何这样做的例子,我在文档中也找不到任何东西。

例如,您想为博客制作一个标签云组件,该组件将显示在所有“帖子”页面的侧边栏中以及单个“/tag-cloud”页面上。您可以使用 like<TagCloud limit={20} /><TagCloud tags={uniqueTags} />. 为此,您需要查询所有边,将每个tags数组映射减少/提取到唯一的、有序的唯一标签字符串集。

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

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

4

2 回答 2

3

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

pages/index.js我在我的问题中引用并且我认为不是最佳的当前解决方案是在(或您使用的任何地方createPage({path, component, context})并将数据注入到 中构建顶级可重用组件所需的所有数据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;
于 2017-10-07T09:55:40.267 回答
3

您可以在 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
  }
`
于 2018-01-21T19:55:08.003 回答