Dedicated to the Hydrogen framework, headless commerce, and building custom storefronts using the Storefront API.
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);
}
});
Solved! Go to the solution
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.
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));
};
To learn more visit the Shopify Help Center or the Community Blog.
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.
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));
};
To learn more visit the Shopify Help Center or the Community Blog.
@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