Query collection by id Variable $id of type ID! was provided invalid value

Tourist
16 0 2

Hi

I want to get the products from a specific collection but I am getting following error

bundle.esm.js?74ca:63 Uncaught (in promise) Error: GraphQL error: Variable $id of type ID! was provided invalid value

The strange thing is if I test it via Graphql app from shopify then it works.

Proof:

Screenshot 2021-01-10 at 01.28.28.png

Don't know what I need to do and I hope someone faced with the same issue and can help me. 

My Grapql query looks like this:

export const GET_PRODUCTS_BY_COLLECTION = gql`query ($id: String) {
  collection(id: $id) {
    products(first: 20) {
      edges {
        node {
          id
          title
          images(first: 30) {
            edges {
              node {
                id
                altText
                originalSrc
              }
            }
          }
        }
      }
    }
  }
}`

 

Here is the code of my component:

import { Steps, Button, message, Card, Layout } from 'antd';
import { useQuery } from 'react-apollo';
import React, { useCallback, useEffect, useState } from 'react';
import { GET_ALL_COLLECTIONS, GET_ALL_PRODUCTS, GET_PRODUCTS_BY_COLLECTION } from '../graphql/gql';
import Dropdown from '../Dropdown/Dropdown';
const { Content } = Layout;
const { Meta } = Card;

const { Step } = Steps;

const source = [
  {
    title: 'All Products',
  },
  {
    title: 'Collection'
  }
];

const steps = [
  {
    title: 'Select Source',
    content: 'First-content',
  },
  {
    title: 'Preview',
    content: 'Second-content',
  },
  {
    title: 'Last',
    content: 'Last-content',
  },
];


const Stepper = ({ children }) => {
  const [current, setCurrent] = useState(0);
  const [activeAllProducts, setactiveAllProducts] = useState(false);
  const [activeCollection, setactiveCollection] = useState(false);
  const [activeSubCollection, setactiveSubCollection] = useState(false);
  const [activeNextButton, setactiveNextButton] = useState(false);
  const [collection, setCollection] = useState('');
  const [collectionId, setcollectionId] = useState(null);

  const productsByCollectionId = useQuery(GET_PRODUCTS_BY_COLLECTION)

  console.log(productsByCollectionId)

  const res = useQuery(GET_ALL_PRODUCTS, {
    variables: {
      after: null,
    },
  });

  const { loading, error, data } = useQuery(GET_ALL_COLLECTIONS); //<------------Here is the query

  if (loading) return 'Loading...';
  if (error) return `Error! ${error.message}`;

  const collections = [];
  let images = [];
  const imageNodes = [];
  const nodeImages = [];

  const { data: data2, fetchMore: fetchMore2 } = res;

  if (data2) {
    const edgesData = data2.products.edges;

    const imageData = [...edgesData];

    imageData.forEach((item) => {
      images.push(item.node.images);
    })

    const imageEdges = [...images];
    imageEdges.forEach((item) => {
      imageNodes.push(item);
    })

    imageNodes.map((item) => {
      item.edges.map((itemSec) => {
        nodeImages.push(itemSec.node)
      })
    })
  }

  const { edges } = data.collections;
  edges.forEach((collection) => {
    collections.push(collection.node)
  })


  const selectedSource = (item) => {
    console.log(item)
    switch (item) {
      case 'All Products':
        setactiveAllProducts(true)
        setactiveCollection(false);
        setactiveNextButton(true);
        break;

      case 'Collection':
        setactiveAllProducts(false)
        setactiveNextButton(false);
        setactiveCollection(true);
        break;
      default:
        setactiveSubCollection(true);
        setactiveNextButton(true);
        setCollection(item);
    }
  };


  const next = () => {
    setCurrent(current + 1);

    if (activeSubCollection) {
      const collectionData = data.collections.edges;
      const res = collectionData.filter((item) => {
        console.log(item.node.title === collection)
        return item.node.title === collection;
      })

      const collectionId = res[0].node.id;
  
      productsByCollectionId.refetch({ <------------Here is the refetch and the variable I pass to graphql
        variables: {
          id: btoa("gid://shopify/Collection/239930736810")
        }
      }

      )
    }
  };

  const prev = () => {
    setCurrent(current - 1);
  };

  return (
    <>
      <Steps current={current}>
        {steps.map(item => (
          <Step key={item.title} title={item.title} />
        ))}
      </Steps>
      <div className="steps-content">
        <Content>
          {(current === 0) ?
            <div className="nextEachOther">
              <Dropdown data={source} selectedSource={selectedSource} />
              {
                activeCollection ? <Dropdown data={collections} value={true} selectedSource={selectedSource} /> : null
              }
            </div>
            : null}
          {(current === 1) ?
            <div>
              <div className="nextEachOther" >
                {nodeImages.map((item) => {
                  return (
                    <Card
                      hoverable
                      key={item.id}
                      style={{ width: 190, margin: 5 }}
                      cover={<img alt={item.altText} src={item.originalSrc} />}
                    >
                      <Meta title={item.altText.substr(0, 20)} />
                    </Card>
                  )

                })}
                {data2.products.pageInfo.hasNextPage ?
                  <Button type="danger" style={{ width: '100%', margin: 25 }} onClick={() => {
                    if (data2.products.pageInfo.hasNextPage) {
                      fetchMore2({
                        variables: {
                          after: data2.products.edges[data2.products.edges.length - 1].cursor,
                        },
                        updateQuery: (prevResult, { fetchMoreResult }) => {
                          if (!fetchMoreResult) return prevResult;
                          fetchMoreResult.products.edges = [
                            ...prevResult.products.edges,
                            ...fetchMoreResult.products.edges,
                          ];
                          return fetchMoreResult;
                        },
                      });
                    }
                  }}>
                    Load more..
          </Button> : null}
              </div>

            </div>
            : null}

        </Content>

      </div>
      <div className="steps-action">
        {(current < steps.length - 1 && activeNextButton) && (
          <Button type="primary" onClick={() => next()}>
            Next
          </Button>
        )}
        {current === steps.length - 1 && (
          <Button type="primary" onClick={() => message.success('Processing complete!')}>
            Done
          </Button>
        )}
        {current > 0 && (
          <Button style={{ margin: '0 8px' }} onClick={() => prev()}>
            Previous
          </Button>

        )}
      </div>
    </>
  );
};
export default Stepper;

 

 

0 Likes
Shopify Staff
Shopify Staff
18 2 2

Hi @Ali_Go,

I believe the issue you're facing is because you're specifying the wrong input type for your GraphQL query in your React code. Note the difference in the type of the input $id you specify - in GraphiQL it's ID! but in your React code you specify String . The error indicates the variable $id should be of typeID!

Hope this helps.

Best,

Seth.

0 Likes
Tourist
16 0 2

Hi @syf_ 

I tried both ways String and ID!. 

With ID! within Reacht I am getting an error: The input type is wrong. I am passing it as string or how I can pass the "gid://..." as ID? 

 

Thanks

Ali

0 Likes