Hi all,
I’m new to both Remix and GraphQL (although I have experience with React & TypeScript development).
I’m building an app that uses a Prisma database as it’s primary storage. When the page loads, I use the loader
Remix function to load data from the database - this works as expected. However, I need to allow the user to import/sync data from the Shopify Admin API into the database when they click a button. I’ve read all of the docs and countless online blogs, and I’ve surmised that:
loader
is used to makeGET
requests (orquery
in GraphQL) when a route/page loadsaction
is used to makePOST
/PUT
requests (ormutation
in GraphQL) when an action on the page is taken (i.e. form submit)useFetcher
can be used to make requests dynamically, by usingfetcher.load
to load a route
To get this working, I have done the following:
app.customers.jsx
const fetcher = useFetcher();
const importCustomers = () => {
if (fetcher.state !== "idle") return;
fetcher.load("/app/import"); // Triggers data fetching
}
useEffect(() => {
if (!fetcher.data || fetcher.state !== "idle") {
return;
}
}, [fetcher.state, fetcher.data]);
return (
<Page
primaryAction={{ content: fetcher.state !== "idle" ? "Generating report..." : "Generate report", onAction: () => importCustomers() }}
/>
)
app.import.js
import { getAdminCustomers } from "../models/customers.server";
import { authenticate } from "../shopify.server";
export async function loader({ request }) {
const { admin } = await authenticate.admin(request);
const customers = await getAdminCustomers(admin);
return Response.json(customers)
}
customers.server.js
export const getAdminCustomers = async (admin) => {
try {
const response = await admin.graphql(
`#graphql
query getCustomers {
customerSegmentMembers(first: 1000, query: "customer_tags CONTAINS 'b2b'") {
edges {
node {
id
displayName
defaultEmailAddress {
emailAddress
}
}
}
}
}`
);
if (response.ok) {
const {
data: {
customerSegmentMembers: { edges }
}
} = await response.json();
return edges;
}
} catch (error) {
return error;
}
}
The above code works - when the user clicks the ‘Import’ button, the app loads the route /app/import
, which runs the loader, calls the API via GraphQL and returns the data. However, surely there must be a better way of making API calls dynamically?
Apologies if I’ve misinterpreted Remix/GraphQL, and that actually they aren’t designed for this type of usecase. Any advice would be appreciated.