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