为什么在Gatsby的两种不同布局上无法具有两个StaticQuery元素的相同名称?

Hel*_*nda 2 reactjs graphql gatsby

例如,如果我有两个布局,而我想使用相同的布局,则需要为每个布局命名不同的StaticQuery:

layoutA.js

const LayoutA = ({ children }) => (
  <StaticQuery
    query={graphql`
      query SiteTitleQuery {
        site {
          siteMetadata {
            title
          }
        }
      }
    `}
Run Code Online (Sandbox Code Playgroud)

layoutB.js

const LayoutB = ({ children }) => (
  <StaticQuery
    query={graphql`
      query SiteTitleQuery {
        site {
          siteMetadata {
            title
          }
        }
      }
    `}
Run Code Online (Sandbox Code Playgroud)

以上将导致以下错误:

error GraphQL Error编译站点的GraphQL查询时出错。错误:RelayParser:遇到一个或多个文档的重复定义:每个文档必须具有唯一的名称。重复的文件:-SiteTitleQuery

从某种意义上说,它们是两个不同的StaticQueries,它们用于两个不同的页面(布局),并且可以接受,除非可以在页面之间共享StaticQueries。

Lek*_*rts 6

我个人并不真正在乎这个名称,实际上您可以完全忽略该名称,而盖茨比将单独使用一些唯一的随机名称。如果选择给它命名,则必须给它两个不同的名称,没有解决方法。

但是,可以使用Hooks版本的StaticQuery: useStaticQuery

这样,您就不会重复。


因此,在一个新组件中,您可以编写以下内容:

import { useStaticQuery, graphql } from 'gatsby'

function useTitle() {
  const data = useStaticQuery(graphql`
    query {
      site {
        siteMetadata {
          title
        }
      }
    }
  `)

  return data.site.siteMetadata.title
}

export default useTitle
Run Code Online (Sandbox Code Playgroud)

并在您的布局中使用它:

import useTitle from './useTitle'

const LayoutA = ({ children }) => {
  const title = useTitle()

  return <div><h1>{title}</h1>{children}</div>
}
Run Code Online (Sandbox Code Playgroud)


Der*_*yen 5

@LekoArts 提供了很好的解决方案。我想回答这个问题:为什么两个不同的文件中不可能有相同的查询名称?

Gatsby从您的文件中提取所有 graphql 查询并独立执行它们。如果用户省略了查询名称,将为该查询生成一个名称;但如果它确实有名称,它将与所有其他查询位于同一空间中。

该系统的一个优点是您可以导出任何文件中的片段,并且它将可用于其他查询。插件和包也利用了这一点,例如gatsby-image使用GatsbyImageSharpFluid& GatsbyImageSharpFixed

除了使用useStaticQuery钩子(仅适用于React ^16.8)之外,重复的查询还可以使用片段提取到更小的组件中StaticQuery或变成片段