gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.26k stars 10.31k forks source link

GraphQL Query works in Graphical - Undefined in Development #23812

Closed sambaines closed 4 years ago

sambaines commented 4 years ago

Description

Inconsistent graphQL query definition when pulling in data from Shopify-Source plugin (so this might not be the best place to ask this but in theory it should work) - basically I have two pages which define a graphQL query and pass it as props to the same component (effectively) but one errors as being undefined. Both queries work fine in graphiQL.

This could well be an error with how I am trying to use .map to get through the data but I would expect the data to be defined still and the error thrown up in the map function if that was the problem.

Steps to reproduce

Build a new page, define a new allShopifyCollection query and pass using props to component.

This is the original query which works - new arrivals page passing graphQL query to grid component as prop:

import React from 'react';
import { graphql } from 'gatsby';

import SEO from '../components/seo.js';
import Layout from '../components/Layout/Layout.js';
import Grid from '../components/Grid/Grid.js';

import styling from '../pages/newarrivals.module.scss';

 export const { allShopifyProduct } = 
    graphql`
    query {
      allShopifyProduct(
        limit: 16,
        sort: {
          fields: [createdAt]
          order: DESC
        }
      ) {
        edges {
          node {
            id
            title
            handle
            createdAt
            images {
              id
              originalSrc
              localFile {
                childImageSharp {
                  fluid(maxWidth: 910) {
                    ...GatsbyImageSharpFluid_withWebp_tracedSVG
                  }
                }
              }
            }
            variants {
              price
            }
          }
        }
      }
    }
  `

const NewArrivals = ({ data }) => (
  <Layout>
    <SEO title="New Arrivals" keywords={[`gatsby`, `application`, `react`]} />
    <div className={styling.container}>
        <Grid title={"New Arrivals"} query={data.allShopifyProduct} />
    </div>
  </Layout>
)

export default NewArrivals;

Grid component:

import React, { useContext } from 'react';
import { Link } from 'gatsby';

import StoreContext from '../../context/StoreContext.js';
import CategoryNav from '../Navigation/CategoryNav.js';

import styling from '../Grid/grid.module.scss';

const Grid = ({ title, catnav, collection, query }) => {
    const { store: {checkout} } = useContext(StoreContext);
    return (
        <div className={styling.container}>
        <h1>{title}</h1>
            {catnav ? <CategoryNav /> : null }
            {query.edges
                ? query.edges.map(({ node: { id, handle, title, images: [firstImage], variants: [firstVariant] } }) => (
                <div key={id} className={styling.block}>
                    <Link to={`/product/${handle}/`}>
                    {firstImage && firstImage.localFile &&
                        (<img
                        src={firstImage.originalSrc}
                        alt={handle}
                        />)}
                    </Link>
                    <p className={styling.title}>{title}</p>
                    <p className={styling.price}><span className={styling.priceTag}>£</span>{firstVariant.price}</p>
                </div>
                ))
                : <p>Something went wrong!</p>}
        </div>
    )

}

export default Grid;

When trying to do the same on another page but for a collection of products:

import React from 'react';
import { graphql } from 'gatsby';

import SEO from '../../components/seo.js';
import Layout from '../../components/Layout/Layout.js';
import GridTest from '../../components/Grid/GridTest.js';

import styling from '../categories/categories.module.scss';

export const { allShopifyCollection } = 
    graphql`
    query {
        allShopifyCollection(filter: {handle: {eq: "necklaces"}}) {
          nodes {
            handle
            products {
              handle
              id
              title
              variants {
                price
              }
              images {
                id
                originalSrc
                localFile {
                  url
                }
              }
            }
          }
        }
      }
  `

const Necklaces = ({ data }) => (
  <Layout>
    <SEO title="Necklaces" keywords={[`gatsby`, `application`, `react`]} />
    <div className={styling.container}>
        <GridTest title={"Jewellery Categories"} catnav={true} collection={true} query={data.allShopifyCollection} />
    </div>
  </Layout>
)

export default Necklaces;

Made a copy of the grid component called GridTest to play with:

import React, { useContext } from 'react';
import { Link } from 'gatsby';

import StoreContext from '../../context/StoreContext.js';
import CategoryNav from '../Navigation/CategoryNav.js';

import styling from '../Grid/grid.module.scss';

const GridTest = ({ title, catnav, collection, query }) => {
    const { store: {checkout} } = useContext(StoreContext);
    return (
        <div className={styling.container}>
        <h1>{title}</h1>
            {catnav ? <CategoryNav /> : null }
            {collection
                ? query.nodes.map(({ products: { id, handle, title, images: [firstImage], variants: [firstVariant] } }) => (
                <div key={id} className={styling.block}>
                    <Link to={`/product/${handle}/`}>
                    {firstImage && firstImage.localFile &&
                        (<img
                        src={firstImage.originalSrc}
                        alt={handle}
                        />)}
                    </Link>
                    <p className={styling.title}>{title}</p>
                    <p className={styling.price}><span className={styling.priceTag}>£</span>{firstVariant.price}</p>
                </div>
                ))
                : <p>Something went wrong!</p>}
        </div>
    )

}

export default GridTest;

Expected result

I would expect both queries to produce a page with the data available to .map through, as happens with the 'new arrivals' page.

Actual result

_ref2$products$images is undefined error page.

Environment

System: OS: Windows 10 10.0.18362 CPU: (4) x64 Intel(R) Core(TM) i5-7600K CPU @ 3.80GHz Binaries: Node: 12.16.1 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.4 - C:\Program Files (x86)\Yarn\bin\yarn.CMD npm: 5.6.0 - C:\Program Files\nodejs\npm.CMD Browsers: Edge: 44.18362.449.0 npmPackages: gatsby: ^2.19.34 => 2.19.34 gatsby-cli: ^2.11.8 => 2.11.8 gatsby-image: ^2.2.29 => 2.2.37 gatsby-plugin-google-analytics: ^2.0.13 => 2.1.23 gatsby-plugin-layout: ^1.0.11 => 1.1.13 gatsby-plugin-manifest: ^2.2.23 => 2.2.34 gatsby-plugin-offline: ^3.0.16 => 3.0.30 gatsby-plugin-react-helmet: ^3.1.13 => 3.1.18 gatsby-plugin-root-import: ^2.0.5 => 2.0.5 gatsby-plugin-sass: ^2.1.30 => 2.1.30 gatsby-plugin-sharp: ^2.2.32 => 2.3.10 gatsby-source-filesystem: ^2.1.33 => 2.1.33 gatsby-source-shopify: ^3.0.46 => 3.0.46 gatsby-transformer-sharp: ^2.3.0 => 2.3.9

danabrit commented 4 years ago

Hi @sambaines !

Sorry to hear you're running into an issue. To help us best begin debugging the underlying cause, it is incredibly helpful if you're able to create a minimal reproduction. This is a simplified example of the issue that makes it clear and obvious what the issue is and how we can begin to debug it.

If you're up for it, we'd very much appreciate if you could provide a minimal reproduction and we'll be able to take another look.

Thanks for using Gatsby! 💜

sambaines commented 4 years ago

Hey @danabrit - made a minimal reproduction here - for reference the all.js page works correctly here when passing a graphQL query to the Grid.js component and uses the allShopifyProduct endpoint query (?!), the necklaces.js and necklaces-test.js files try to use the allShopifyCollection (which I have tried to mirror the same query to the all.js one i.e. query.edges.node... for when I map it) return an query.edges.node undefined.

Hope that is enough detail (and that I am not making some really basic coding error).

sambaines commented 4 years ago

Ok sorry this was a waste of time - need to brush up on my .map skills - managed to get this to work for both allShopifyCollection and shopifyCollection endpoints.