目前是否可以在 Gatsby 中构建具有自己的 graphql 查询的可重用组件?如果不是,目前将数据传递给可重用组件的“耦合”最少的方法是什么?我似乎找不到任何执行此操作的示例,而且我在文档中也找不到任何内容。
例如,您想要为博客创建一个标签云组件,它会显示在所有“post”页面的侧边栏以及单个“/tag-cloud”页面上。你可以像<TagCloud limit={20} />
一样使用或 <TagCloud tags={uniqueTags} />
.为此,您需要查询所有边,map-reduce/提取每个 tags
排列成一组唯一的、有序的唯一标记字符串。
或者,假设您想要一个排除当前产品的目录页面的“其他产品”组件。在这里,你可能有 <ProductsList exclude={currentProduct} />
.这将是构建时的直接过滤查询。
我能看到的唯一方法是对来自 createPages()
的查询结果进行猴子修补。或者通过 context
传递数据在 createPage({path, component, context})
.如果这发生在 gatsby-node.js
?还有其他方法吗?
最佳答案
我正在回答我自己的问题。如果有人有更好的解决方案,请提交,我会很乐意接受。
我在我的问题中引用了我当前的解决方案,我认为这是次优的,它是在 pages/index.js
(或任何你使用 createPage({path, component, context})
并将数据注入(inject)到 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;
关于javascript - 具有自己查询的 Gatsby 可重用组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46519893/