Solved

Which is Backend vs Frontend? (GraphQL Querying on Node + Express + React + Apollo + App Bridge)

buildpath
Shopify Partner
59 11 19

I'm currently trying to query GraphQL Admin API in my public Node + React Shopify app.

When I query GraphQL, I have no idea if I'm querying Admin API or Storefront API, and I have no idea where I can specify which one to query... I'm trying to get a list of the last 10 recent orders, but I get a 400 bad request error saying, "Cannot query field "orders" on type "Query" which probably means I'm querying Storefront API instead of Admin API.

 

I understand the frontend of my app cannot query Admin API. So, please check my code snippets below - my question is... Am I querying GraphQL from the frontend or the backend? To me, it looks like I'm sending the query to my app's backend which uses Apollo and to actually perform the query. Am I wrong?

 

This is the code in my react component:

 

 

 

const app = useAppBridge();
  const fetch = userLoggedInFetch(app);
  const ORDERS_QUERY = gql`
    query getOrders {
      orders(first:5) {
        edges {
          node {
            id
          }
        }
      }
    }   
  `;
  const { loading, error, data, refetch } = useQuery(ORDERS_QUERY);
  if (loading) {
    console.log('loading...');
    return <Loading />;
  }

  if (error) {
    console.log('error trying to get orders: ', error);
    return (
      <Banner status="critical">There was an issue loading orders.</Banner>
    );
  }

 

 

 

This is my Apollo setup in App.jsx:

 

 

function MyProvider({ children }) {
  const app = useAppBridge();
  const client = new ApolloClient({
    cache: new InMemoryCache(),
    link: new HttpLink({
      credentials: "include",
      fetch: userLoggedInFetch(app),
    }),
  });

  return <ApolloProvider client={client}>{children}</ApolloProvider>;
}

 

 

 

All pages are wrapped in the Apollo Provider. As I saw in Apollo Client documentation, by default, GraphQL queries are posted to the /graphql endpoint.

 

On the backend, in my Node/Express server setup file (/server/index.js), this is the config for the /graphql endpoint:

 

 

app.post("/graphql", verifyRequest(app), async (req, res) => {
    try {
      const response = await Shopify.Utils.graphqlProxy(req, res);
      res.status(200).send(response.body);
    } catch (error) {
      res.status(500).send(error.message);
    }
  });

 

 

 

Ecom entrepreneur since 2004 | Shopify App developer since 2021 | Shopify merchant and theme developer since 2016
Accepted Solutions (2)

buildpath
Shopify Partner
59 11 19

This is an accepted solution.

Ok, I was assuming my understanding was incorrect because of being unable to fix the problems I was encountering. For anyone reading, yes, the react components are frontend and the node server index.js are backend.

Ecom entrepreneur since 2004 | Shopify App developer since 2021 | Shopify merchant and theme developer since 2016

View solution in original post

stevemar
Shopify Staff (Retired)
3 1 0

This is an accepted solution.

Not much to add here. You've summed it up nicely @buildpath.

 

When I have an app with Node.js on the backend and React in the frontend, and I'm trying to use the GraphQL Admin APIs, I specify the query in the frontend, like so... (it's an example showing a list of Shopify Channels) in it's own component.

const CHANNELS_QUERY = gql`
  query ChannelQuery {
    channels(first: 100) {
      nodes {
        id
        name
      }
    }
  }`;

 

And then call a helper function, which in turn makes an authenticated call to my graphql endpoint on the backend.

 

  const { isLoading, error, data } = useShopifyQuery({
    key: "channels",
    query: CHANNELS_QUERY,
  });

  let channelsData = [];
  if (data) {
    channelsData = data.data.channels.nodes;
    console.log("channelsData", channelsData);
  }

 

For completeness, the helper function calling the backend with an authenticated fetch call: 

 

import { useQuery } from "react-query";
import { GraphQLClient } from "graphql-request";

import { useAuthenticatedFetch } from "./useAuthenticatedFetch.js";

export const useShopifyQuery = ({ key, query, variables }) => {
  const authenticatedFetch = useAuthenticatedFetch();
  const graphQLClient = new GraphQLClient("/api/graphql", {
    fetch: authenticatedFetch,
  });

  return useQuery(key, async () => graphQLClient.rawRequest(query, variables));
};
 
In the backend, my function for handling `/graphql` endpoints looks identical to yours.
 

To learn more visit the Shopify Help Center or the Community Blog.

View solution in original post

Replies 3 (3)

buildpath
Shopify Partner
59 11 19

This is an accepted solution.

Ok, I was assuming my understanding was incorrect because of being unable to fix the problems I was encountering. For anyone reading, yes, the react components are frontend and the node server index.js are backend.

Ecom entrepreneur since 2004 | Shopify App developer since 2021 | Shopify merchant and theme developer since 2016
stevemar
Shopify Staff (Retired)
3 1 0

This is an accepted solution.

Not much to add here. You've summed it up nicely @buildpath.

 

When I have an app with Node.js on the backend and React in the frontend, and I'm trying to use the GraphQL Admin APIs, I specify the query in the frontend, like so... (it's an example showing a list of Shopify Channels) in it's own component.

const CHANNELS_QUERY = gql`
  query ChannelQuery {
    channels(first: 100) {
      nodes {
        id
        name
      }
    }
  }`;

 

And then call a helper function, which in turn makes an authenticated call to my graphql endpoint on the backend.

 

  const { isLoading, error, data } = useShopifyQuery({
    key: "channels",
    query: CHANNELS_QUERY,
  });

  let channelsData = [];
  if (data) {
    channelsData = data.data.channels.nodes;
    console.log("channelsData", channelsData);
  }

 

For completeness, the helper function calling the backend with an authenticated fetch call: 

 

import { useQuery } from "react-query";
import { GraphQLClient } from "graphql-request";

import { useAuthenticatedFetch } from "./useAuthenticatedFetch.js";

export const useShopifyQuery = ({ key, query, variables }) => {
  const authenticatedFetch = useAuthenticatedFetch();
  const graphQLClient = new GraphQLClient("/api/graphql", {
    fetch: authenticatedFetch,
  });

  return useQuery(key, async () => graphQLClient.rawRequest(query, variables));
};
 
In the backend, my function for handling `/graphql` endpoints looks identical to yours.
 

To learn more visit the Shopify Help Center or the Community Blog.

buildpath
Shopify Partner
59 11 19

@stevemar thank you for making this extra clear for me, and for anyone else who finds my post and possibly gets confused by me. I think your answer is really helpful. Thanks again

Ecom entrepreneur since 2004 | Shopify App developer since 2021 | Shopify merchant and theme developer since 2016