Gatsby 具有自己查询的可重用组件
Posted
技术标签:
【中文标题】Gatsby 具有自己查询的可重用组件【英文标题】:Gatsby reusable components with own query 【发布时间】:2018-03-13 04:37:42 【问题描述】:目前是否可以在 Gatsby 中构建具有自己的 graphql 查询的可重用组件?如果不是,那么目前将数据传递给可重用组件的最“耦合”方式是什么?我似乎找不到任何执行此操作的示例,并且在文档中找不到任何内容。
例如,您想为博客制作一个标签云组件,该组件将显示在所有“帖子”页面的侧边栏中以及单个“/tag-cloud”页面上。您可以使用 <TagCloud limit=20 />
或 <TagCloud tags=uniqueTags />
。为此,您需要查询所有边,将每个 tags
数组映射减少/提取到唯一的、有序的唯一标签字符串集。
或者,假设您想要一个排除当前产品的目录页面的“其他产品”组件。在这里,您可能有<ProductsList exclude=currentProduct />
。这将是构建时直接过滤的查询。
我能看到这样做的唯一方法是对来自createPages()
的查询结果进行猴子修补,或者通过context
在createPage(path, component, context)
中传递数据。这应该发生在gatsby-node.js
吗?还有其他方法吗?
【问题讨论】:
快速回答是片段github.com/gatsbyjs/gatsby/… 希望我有时间尽快写下这方面的文档。 感谢@KyleMathews(非常感谢 Gatsby)。完成后我会调查并更新。 @KyleMathews - 仍然没有看到它。片段(在查询中)似乎只接收到它们扩展的单个 graphql 边缘。我没有看到任何可以访问的示例,例如allMarkdownRemark
。对于头像示例,作为另一个示例,您将如何在单个帖子页面上显示所有网站作者的所有头像列表?或者,如果我可以在gatsby-node.js
中建立一个列表,我应该如何将它传递给所有页面?
【参考方案1】:
我正在回答我自己的问题。如果有人有更好的解决方案,请提交,我很乐意接受。
我当前的解决方案,我在我的问题中引用并且我认为不是最理想的,是在pages/index.js
(或您使用createPage(path, component, context)
的任何地方)构建***可重用组件所需的所有数据并将数据注入context
。这使得它可以通过pathContext
属性提供给component
构造函数。名称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;
【讨论】:
我发现自己实现了相同的方法。如果这种方法有任何危险,或者解释如何使用片段来实现相同的结果,我会很高兴从@KyleMathews 到这里。 如果不查看您的数据模型(或了解您的源插件),很难了解更多信息,但理想情况下,您可以通过每个页面组件中的pageQuery
直接从 GraphQL 获取所有标签。这显示了一般方法github.com/gatsbyjs/gatsby/blob/master/docs/docs/…【参考方案2】:
您可以在 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
`
【讨论】:
以上是关于Gatsby 具有自己查询的可重用组件的主要内容,如果未能解决你的问题,请参考以下文章