目前Gatsby中是否可以构建具有自己的graphql查询的可重用组件?如果没有,目前将数据传递给可重用组件的最小“耦合”方式是什么?我似乎无法找到任何这样做的例子,我在文档中找不到任何东西.
比如说,您想为博客创建一个标签云组件,该组件将显示在所有“发布”页面的侧栏以及单个“/ tag-cloud”页面上.您可以使用< TagCloud limit = {20} />或< TagCloud tags = {uniqueTags} />.为此,您需要查询所有边,将每个标记数组map-reduce / extract下移到唯一的,有序的唯一标记字符串集.
或者,假设您想要一个排除当前产品的目录页面的“其他产品”组件.在这里,您可能有< ProductsList exclude = {currentProduct} />.这将是构建时的直接过滤查询.
我可以看到这样做的唯一方法是从createPages()中修补查询结果,或者通过createPage({path,component,context})中的上下文传递数据.这应该发生在gatsby-node.js吗?还有其他方法吗?
解决方法:
我在回答我自己的问题.如果有人有更好的解决方案,请提交,我很乐意接受.
我在我的问题中引用的当前解决方案,我认为不是最理想的,是构建pages / index.js中的*可重用组件所需的所有数据(或者使用createPage({path,component,context}的任何地方)并将数据注入上下文.这使得组件构造函数可以通过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;