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

时间:2017-10-02 05:20:48

标签: javascript graphql gatsby

Gatsby目前是否可以构建具有自己的graphql查询的可重用组件?如果没有,目前最少的是什么?#34;耦合"将数据传递给可重用组件的方法?我似乎找不到任何这样做的例子,我在文档中找不到任何内容。

比如说,你想为一个博客制作一个标签云组件,这个组件会显示在所有&#34; post&#34;的旁边栏中。页面以及单个&#34; / tag-cloud&#34;页。您可以使用<TagCloud limit={20} /><TagCloud tags={uniqueTags} />。为此,您需要查询所有边,将每个tags数组map-reduce / extract下拉为唯一的,有序的唯一标记字符串集。

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

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

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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
  }
`