GraphQL 查询适用于 Gatsby 页面,但不适用于类组件

Posted

技术标签:

【中文标题】GraphQL 查询适用于 Gatsby 页面,但不适用于类组件【英文标题】:GraphQL query works in Gatsby page but not inside class component 【发布时间】:2019-12-27 22:41:00 【问题描述】:

有几个类似的问题,但没有一个能帮助我真正理解在除 pages 文件夹中的组件之外的(类)组件中使用 GraphQL。

我的项目结构如下:

-src
--components
---aboutBody
----index.js
--pages
---about.js

我有一个名为about(棱镜单页类型)的页面组件,并设置了一些组件来“填充”这个页面(为了更好的可读性而进行了清理)。

class AboutPage extends Component 

  render() 
    return (
        <LayoutDefault>
          <AboutBody
            introHeadline=this.props.data.prismicAbout.data.intro_headline.text
            introParagraph=this.props.data.prismicAbout.data.intro_paragraph.text
          />
        </LayoutDefault>
    )
  



export default AboutPage

这就是我的查询的样子(在两个文件中都这样):

export const aboutQuery = graphql`
  query About 
    prismicAbout 
      data 

        # Intro Block
        intro_headline 
          text
        
        intro_paragraph 
          text
        
      
    
  
`

(如果我在底部缺少一个括号,这是由于清理了 SO 的查询示例 - 如前所述,它在我的页面组件中工作)。

我的 graphql 查询位于 AboutPage 页面组件的底部。它就像一个魅力和预期的那样工作。

但是为了稍微清理一下这个页面,我想创建适当的组件并将我的查询放在每个组件中(例如aboutBodyaboutCarousel),再次清理一下:

class AboutBody extends Component 

  render() 

    return (
      <StyledIntro>
        <h3>About</h3>
        <h1>this.props.data.prismicAbout.data.intro_headline.text</h1>
      </StyledIntro>
    )
  



export default AboutBody

然后我从我的about 页面组件中删除了查询并将其放入我的AboutBody 组件中(完全如上所示的方式)。

但是这样它总是返回错误Cannot read property 'prismicAbout' of undefined(我什至不能控制台记录数据,它总是返回相同的错误)。

我在两个文件中都使用了import graphql from "gatsby"

长话短说,我怎样才能实现在我的类组件中放置查询并只呈现组件而不澄清我的页面组件中的道具,如下所示:

class AboutPage extends Component 

  render() 
    return (
        <LayoutDefault>
          <AboutBody />
        </LayoutDefault>
    )
  


一些博客文章提到了 GraphQL 查询片段,但不确定这是正确的用例还是只是一个愚蠢的初学者错误......

【问题讨论】:

【参考方案1】:

那是因为你不能在你的组件中使用这样的 graphql。

要在组件中使用 graphql,您有两个选择:useStaticQuery 函数或 StaticQuery 组件,都来自 graphql

对于useStaticQuery

import React from "react"
import  useStaticQuery, graphql  from "gatsby"

const MyElement = () => 
  const data = useStaticQuery(graphql`
     query About 
       prismicAbout 
         data 
           intro_headline 
             text
           
           intro_paragraph 
             text
           
         
       
     
   `)

   return (
      <StyledIntro>
        <h3>About</h3>
        <h1>this.props.data.prismicAbout.data.intro_headline.text</h1>
      </StyledIntro>
   )


export default MyElement

staticQuery

import React from 'react'
import  StaticQuery, graphql  from 'gatsby';

const MyElement = () => 
   return(
      <StaticQuery
            query About 
              prismicAbout 
                data 
                   intro_headline 
                       text
                       
                       intro_paragraph 
                          text
                       
                   
                
             
         `
         render=data => (
            <StyledIntro>
               <h3>About</h3>
               <h1>this.props.data.prismicAbout.data.intro_headline.text</h1>
            </StyledIntro>
         )
      />
   )


export default MyElement

希望对您有所帮助!

【讨论】:

谢谢 Logan Blangenois 和 ksav。这就像魅力一样,完美地解释了它。赞赏。【参考方案2】:

您只能在页面组件中使用类似的查询。一种选择是只在页面中查询它,然后将数据作为道具传递给您的组件。另一种是在组件中使用静态查询。

如果您的查询中有变量,则不能使用静态查询。在这种情况下,您应该在页面中全部查询,然后将其传入,或者您可以将与该组件相关的查询部分放在该组件文件中的片段中,然后在页面查询中使用该片段。

在组件中使用片段然后将数据传递给组件的示例:

// MyComponent.js
import React from "react"
import  graphql  from 'gatsby'

const MyComponent = (props) => 

  const  myProp:  someData    = props

  return (
    <div>
        my awesome component
    </div>
  )


export default MyComponent

export const query = graphql`
  fragment MyAwesomeFragment on Site 
     someData 
         item
     
  
`
// MyPage.js
import React from "react"
import  graphql  from "gatsby"

import MyComponent from "../components/MyComponent"

export default ( data ) => 
  return (
    <div>
      /*
        You can pass all the data from the fragment
        back to the component that defined it
      */
      <MyComponent myProp=data.site.someData />
    </div>
  )

export const query = graphql`
  query 
    site 
      ...MyAwesomeFragment
    
  
`

在Gatsby docs.中阅读有关使用片段的更多信息

【讨论】:

感谢 Caleb Barnes,很好的解释。真的很感激。【参考方案3】:

如果您需要在基于类的组件中呈现查询。这对我有用:

import React,  Component  from 'react';
import  StaticQuery, graphql  from 'gatsby';

class Layout extends Component 
  render() 
    return (
      <StaticQuery
        query=graphql`
          query SiteTitleQuery 
            site 
              siteMetadata 
                title
              
            
          
        `
        render=data => 
          return (
            <main>
              !data && <p>Loading...</p>
              data && data.site.siteMetadata.title
            </main>
          )
        
      />
    );
  

【讨论】:

以上是关于GraphQL 查询适用于 Gatsby 页面,但不适用于类组件的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL 中的复杂查询变量(通过 Gatsby)

Gatsby 查询在 graphql 编辑器中有效,但在反应代码中无效

如何在 graphQL 中获取 Gatsby 页面 HTML

gatsby-source-drupal 不显示 graphql 查询

[Gatsby][GraphQL]:从另一个查询中检索过滤器参数后运行查询

在 Gatsby 中从 graphQL 查询创建 slug