Graphql query result returning correctly in the UI, but data showing as "undefined" inside app

Viewed 260

I'm working on a Gatsby project where I have a query in Graphql from a JSON data that is returning all the data correctly in the Graph IU and I can even log it out and see the result in the browser devtools. But for some reason when I'm shortening my Graphql fields to use short names, only part of the data is going through as you gonna see in the code below:

Here is the StaticQuery component:

import { useStaticQuery, graphql } from "gatsby"

export const UseFooterDataQuery = () => {
  const allFooterData = useStaticQuery(graphql`
    query FooterDataQuery {
      allDataJson {
        edges {
          node {
            id
            title
            url {
              id
              linkName
              linkUrl
            }
          }
        }
      }
    }
  `)
  return allFooterData
}

Here is the result of the same query in the Graphql IU:

{
  "data": {
    "allDataJson": {
      "edges": [
        {
          "node": {
            "id": "8e2be307-9298-52b2-9a78-cf1a9dfa5b35",
            "title": "Features",
            "url": [
              {
                "id": "022",
                "linkName": "Version Control",
                "linkUrl": "version-control"
              },
              {
                "id": "023",
                "linkName": "Design Collaboration",
                "linkUrl": "design-collaboration"
              },
              {
                "id": "024",
                "linkName": "Developer Handoff",
                "linkUrl": "developer-handoff"
              }
            ]
          }
        }
      ]
    }
  },
  "extensions": {}
}

Here is my function component. See that I'm console logging the UseFooterDataQuery() function and the return allFooterList where I'm only shortening the Graphql field names:

import React from "react"
import { Link } from "gatsby"
import { UseFooterDataQuery } from "../hooks/UseFooterDataQuery"

export default function Footer() {
  const getAllFooterList = () => {
    const allFooterList = []
    const allFooter = UseFooterDataQuery()
    allFooter.allDataJson.edges.forEach(footerEdge => {
      allFooterList.push({
        id: footerEdge.node.id,
        title: footerEdge.node.title,
        linkName: footerEdge.node.url.linkName,
        linkUrl: footerEdge.node.url.linkUrl,
        linkId: footerEdge.node.url.id,
      })
    })
    return allFooterList
  }

  const allFooterList = getAllFooterList()

  console.log(UseFooterDataQuery())
  console.log(allFooterList)

  return (
    <FooterSection>
      <FooterContainer>
        {allFooterList.map(data => {
          return (
            <div key={data.id}>
              <h3>{data.title}</h3>
              <ul>
                <li>
                  <Link to={`/${data.linkUrl}`}>{data.linkName}</Link>
                </li>
              </ul>
            </div>
          )
        })}
      </FooterContainer>
      <div>
        © {new Date().getFullYear()}, Built with
        {` `}
        <a href="https://www.gatsbyjs.com">Gatsby</a>
      </div>
    </FooterSection>
  )
}

Here the return of the console logs above. As you can see, The UseFooterDataQuery() function returned all the data, but I can't figure out what's happening with the return of the allFooterList where my data linkId, linkName and linkUrl is undefined.

{…}​
allDataJson: {…}​​
edges: (1) […]​​​
0: {…}​​​​
node: {…}​​​​​
id: "8e2be307-9298-52b2-9a78-cf1a9dfa5b35"​​​​​
title: "Features"​​​​​
url: (3) […]​​​​​​
0: Object { id: "022", linkName: "Version Control", linkUrl: "version-control" }​​​​​​
1: Object { id: "023", linkName: "Design Collaboration", linkUrl: "design-collaboration" }​​​​​​
2: Object { id: "024", linkName: "Developer Handoff", linkUrl: "developer-handoff" }​​​​​​
length: 3​​​​​​
<prototype>: Array []​​​​​
<prototype>: Object { … }​​​​
<prototype>: Object { … }​​​
length: 1​​​
<prototype>: Array []​​
<prototype>: Object { … }​
<prototype>: {…

allFooterList console.log return:

0: {…}​​
id: "8e2be307-9298-52b2-9a78-cf1a9dfa5b35"​​
linkId: undefined​​
linkName: undefined​​
linkUrl: undefined​​
title: "Features"​​
<prototype>: Object { … }​
length: 1​
<prototype>: [
2 Answers
  • there is no need to duplicate data in state or other vars ... you can simply 'alias' it to shorten code like const items = allFooter.allDataJson.edges;, items.map(...

     {items.map( element => { element.node.id  // array element
     {items.map( {node} => { node.id   // destructured 'node' prop from array element
     {items.map( {node:footerItem} => { footerItem.id   // aliased/renamed destructured array element
    
  • defining 'hook' UseFooterDataQuery in external file is [almost] useless ... no custom logic, no reason ... define only graphql queries in separate ('footer.graphql') files (search for importing gql files)

  • you should use map inside map, outer for node id and title, inner for url:

.

const allFooterData = useStaticQuery( FOOTER_QUERY );
const items = allFooter.allDataJson.edges;

...
   {items.map( {node} => {
      return (
        <div key={node.id}>
          <h3>{node.title}</h3>
            {node.url.map( (data) => {
              return (
                <ul key={data.id}>
                  <li>
                    <Link to={`/${data.linkUrl}`}>{data.linkName}</Link>
                  </li>
                </ul>

@xadm, that works! Thank you very much! Here's how it looks after the adjustments:

import React from "react"
import { Link } from "gatsby"
import { UseFooterDataQuery } from "../hooks/UseFooterDataQuery"

export default function Footer() {
  const allFooterList = UseFooterDataQuery().allDataJson.edges

  // console.log(allFooterList, `==============> FOOTERLIST`)

  return (
    <div>
      <div>
        {allFooterList.map(({ node }) => {
          console.log(node, `==============> NODE`)
          return (
            <div key={node.id}>
              <h3>{node.title}</h3>
              {node.url.map(data => {
                console.log(data, `====================> DATA`)
                return (
                  <ul key={data.id}>
                    <li>
                      <Link to={`/${data.linkUrl}`}>{data.linkName}</Link>
                    </li>
                  </ul>
                )
              })}
            </div>
          )
        })}
      </div>
    </div>
  )
}

Here is the console.log:

{…}​                        ==============> NODE
id: "8e2be307-9298-52b2-9a78-cf1a9dfa5b35"​
title: "Features"​
url: Array(3) [ {…}, {…}, {…} ]​
<prototype>: Object { … }
---------------------------------------------------
{…}                     ====================> DATA
id: "022"​
linkName: "Version Control"​
linkUrl: "version-control"​
<prototype>: Object { … }
---------------------------------------------------
{…}​                        ====================> DATA
id: "023"​
linkName: "Design Collaboration"​
linkUrl: "design-collaboration"​
<prototype>: Object { … }
---------------------------------------------------
{…}​                        ====================> DATA
id: "024"​
linkName: "Developer Handoff"​
linkUrl: "developer-handoff"​
<prototype>: Object { … } 
---------------------------------------------------
Related