Graphql Storefront API always loading no data no error

Topic summary

Issue: GraphQL query (productByHandle) returned undefined/no data, while a mutation (productUpdate) worked when using a hardcoded product ID.

Context: Node.js/React Shopify embedded app using Next.js, Apollo Client, and Shopify App Bridge. Initial setup used authenticatedFetch(app) for API calls.

Key changes that resolved it:

  • Implemented a custom userLoggedInFetch wrapper around authenticatedFetch to detect Shopify reauthorization headers (X-Shopify-API-Request-Failure-Reauthorize and related URL) and redirect via App Bridge (Redirect) to /auth.
  • Pointed Apollo Client’s fetch to userLoggedInFetch(app) with credentials: include.
  • Updated code structure; query remains productByHandle(handle: “your-handle”). Code snippets are central to understanding the fix.

Explanation: If Shopify requires reauthorization, requests can silently fail or return no data; handling these headers and redirecting restores authenticated GraphQL requests.

Outcome: Problem resolved after these adjustments. No exact root cause identified beyond authentication/reauthorization handling. Discussion closed with thanks; no remaining open questions.

Summarized with AI on March 5. AI used: gpt-5.

I am building a nodejs react Shopify app.

On my index.js I have a mutation that works fine when I give a specific hardcode id. Now I’m trying to get that product id by query in order to pass it to the mutation, but that doesn’t return any data.

Here is my code:

import { TitleBar } from '@shopify/app-bridge-react';

import {
  Banner,
  DisplayText,
  EmptyState,
  Frame,
  Heading,
  Layout,
  Page,
  PageActions,
  TextField,
  TextStyle,
  Toast,
  Card,
  ResourceList,
} from '@shopify/polaris';
import { Context } from '@shopify/app-bridge-react';
import gql from 'graphql-tag';
import React from 'react';
import { Query } from 'react-apollo';
import { Mutation } from 'react-apollo';

const UPDATE_PRICE = gql`
  mutation productUpdate($input: ProductInput!) {
	  productUpdate(input: $input) {
		product {
		  id
		}
		userErrors {
		  field
		  message
		}
	  }
	}
`;
const GET_PRODUCT = gql`
  query products {
   productByHandle(handle:"product-handle") {
    id
  }
}`;
var productId = "";

class Index extends React.Component {
  state = {
	showToast: false,
  };
	
  render() {
    return (
		
			
		
	);
  }
}
export default Index;

This is my _app.js

import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";
import App from "next/app";
import { AppProvider } from "@shopify/polaris";
import { Provider, useAppBridge } from "@shopify/app-bridge-react";
import { authenticatedFetch } from "@shopify/app-bridge-utils";
import "@shopify/polaris/dist/styles.css";
import translations from "@shopify/polaris/locales/en.json";

function MyProvider(props) {
  const app = useAppBridge();

  const client = new ApolloClient({
    fetch: authenticatedFetch(app),
    fetchOptions: {
      credentials: "include",
    },
  });

  const Component = props.Component;

  return (
    
  );
}

class MyApp extends App {
  render() {
    const { Component, pageProps, shopOrigin } = this.props;
    return (
      
    );
  }
}

MyApp.getInitialProps = async ({ ctx }) => {
  return {
    shopOrigin: ctx.query.shop,
  };
};

export default MyApp;

Anyone has an idea why data is always undefined?

Hi, do you solve this problem ?

Hey,

I did. I went through several changes on my index.js already so can’t exactly recall what I changed, but here is my index.js & _app.js and hopefully helps you you figure it out.

Index.js

import { TitleBar } from "@shopify/app-bridge-react";

import {
  Banner,
  EmptyState,
  Frame,
  Heading,
  Layout,
  Page,
  PageActions,
  TextField,
  TextStyle,
  Toast,
  Card,
  ResourceList,
} from "@shopify/polaris";
import { Context } from "@shopify/app-bridge-react";
import gql from "graphql-tag";
import React from "react";
import { Query } from "react-apollo";
import { Mutation } from "react-apollo";
import { useQuery } from "@apollo/react-hooks";

const UPDATE_PRICE = gql`
  mutation productUpdate($input: ProductInput!) {
    productUpdate(input: $input) {
      product {
        id
      }
      userErrors {
        field
        message
      }
    }
  }
`;
const GET_PRODUCT = gql`
  query products {
    productByHandle(handle: "your-handle") {
      id
    }
  }
`;

var productID = "";

class Index extends React.Component {
  state = {
    showToast: false,
  };

  render() {
    return (
      
        
      
    );
  }
}
export default Index;

_app.js

import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";
import App from "next/app";
import { AppProvider } from "@shopify/polaris";
import { Provider, useAppBridge } from "@shopify/app-bridge-react";
import { authenticatedFetch } from "@shopify/app-bridge-utils";
import { Redirect } from "@shopify/app-bridge/actions";
import "@shopify/polaris/dist/styles.css";
import translations from "@shopify/polaris/locales/en.json";

function userLoggedInFetch(app) {
  const fetchFunction = authenticatedFetch(app);
  return async (uri, options) => {
    const response = await fetchFunction(uri, options);

    if (response.headers.get("X-Shopify-API-Request-Failure-Reauthorize") === "1") {
      const authUrlHeader = response.headers.get("X-Shopify-API-Request-Failure-Reauthorize-Url");

      const redirect = Redirect.create(app);
      redirect.dispatch(Redirect.Action.APP, authUrlHeader || `/auth`);
      return null;
    }

    return response;
  };
}

function MyProvider(props) {
  const app = useAppBridge();

  const client = new ApolloClient({
    fetch: userLoggedInFetch(app),
    fetchOptions: {
      credentials: "include",
    },
  });

  const Component = props.Component;

  return (
    
  );
}

class MyApp extends App {
  render() {
    const { Component, pageProps, shopOrigin } = this.props;
    return (
      
    );
  }
}

MyApp.getInitialProps = async ({ ctx }) => {
  return {
    shopOrigin: ctx.query.shop,
  };
};

export default MyApp;

Good luck!

1 Like

Thanks a lot!!!