为什么graphql不将我的数据注入到react组件prop中?

时间:2019-10-14 19:01:16

标签: javascript reactjs graphql gatsby

我正在使用此tutorial创建一个将使用Markdown页面的gatsby博客。

我试图创建一个“后中继器”组件,该组件将遍历我的所有帖子,并使用如下形式的frontmatter创建指向它们的链接。

---
path: "/blog/my-first-post"
date: "2019-05-04"
title: "My first blog post"
---

我有一个graphQl查询可以正确提取数据。

graphQl query

我的组件看起来像这样。

import React from "react"

import "../styles/post-repeater.scss"
import { graphql, Link } from "gatsby"

export default function PostRepeater({postQuery}){
    console.log('my data:',postQuery);
    return(

        <>
            {postQuery.map(instance => 
                <div className="post">
                    <h2>{instance.title}</h2>
                    <span className="datePosted">{instance.date}</span>
                    <span className="readTime"></span>
                    <p></p>
                    <Link to={instance.path}>Read More</Link>
                    <hr />
                </div>
            )}
        </>

    )
}

export const postQuery = graphql`
query MyQuery {
    allMarkdownRemark {
      edges {
        node {
          frontmatter {
            path
            title
            date
          }
        }
      }
    }
  }
`

如果我从PostRepeater组件内部放入postQuery的console.log,它将以未定义的形式返回。因此,即使我遵循上面教程中的相同布局,该组件也似乎从未获取数据。

如果从组件外部放置console.log('data', postQuery);,则会在控制台中获得以下内容。

  

数据2575425095

我在做什么错?

2 个答案:

答案 0 :(得分:2)

进行查询后,gatsby将其作为与查询匹配的对象插入。

在您的情况下,如您在GraphiQL中看到的那样,您将获得一个具有初始键data的对象。

{
  "data": {
    "allMarkdownRemark": {
      "edges": [
        {
          "node": {
            "frontmatter": {
              "title": "...",
              "date": ...
            }
          }
        }
      ]
    }
  }
}

您尝试做的是destructing 一个不存在的密钥postQuery

此外,您仍然可以将其记录为组件范围之外的值,作为从export const postQuery导出的值

export const postQuery = graphql`
  query MyQuery {
    allMarkdownRemark {
      edges {
        node {
          frontmatter {
            path
            title
            date
          }
        }
      }
    }
  }
`;

//       v  Logs the query id
console.log('my data:', postQuery);

//                                               v Is not defined
export default function PostRepeater({ data, postQuery }) {

  //                       v Shadowing the outter value of postQuery
  console.log('my data:', postQuery);

  // The query injected as "data" object
  console.log('my data:', data);

  return (
    <>
      //      v Be aware of which object you query, edges is an array
      {data.allMarkdownRemark.edges.map(...)}
    </>
  );
}

答案 1 :(得分:0)

自动附加到props的graphql查询的导出仅适用于页面组件。对于任何非页面组件,您都需要使用StaticQuery组件或useStaticQuery挂钩。

在此处了解更多信息: https://www.gatsbyjs.com/docs/static-query/

这是使用useStaticQuery挂钩的代码外观

import React from "react"

import "../styles/post-repeater.scss"
import { graphql, useStaticQuery, Link } from "gatsby"

export default function PostRepeater() {
  const data = useStaticQuery(graphql`
    query MyQuery {
      allMarkdownRemark {
        edges {
          node {
            frontmatter {
              path
              title
              date
            }
          }
        }
      }
    }
    `)
   // you might have multiple nodes in which case you must use filter 
   // or find to get node which contains your data. 
   const postQuery = data.allMarkdownRemark.edges[0].node.frontmatter;

   return (
     <>
       {postQuery.map(instance => 
         <div className="post">
           <h2>{instance.title}</h2>
           <span className="datePosted">{instance.date}</span>
           <span className="readTime"></span>
           <p></p>
           <Link to={instance.path}>Read More</Link>
           <hr />
         </div>
       )}
     </>
   )

}