Generated Data Loaders
To minimize repetitive work, we automatically generate Remix data loaders by analyzing the page source code. Our parser scans the page for GraphQL queries and calls all of those queries in the generated data loaders.
How It Works
- The parser analyzes the component code and detects GraphQL queries.
- It creates a key-value pair where the key represents the GraphQL document the query uses, and the value refers to the variables used by the query.
- This information is used to generate both server and client loaders.
Example
Consider this component:
// Teams.tsx
const Teams = (props) => {
const [data, { loading }] = useTeamsQuery({ variables: { orgName, pageSize: 10 } });
// rest of the business logic
return (
// component render Markup
)
}
The generated routes.json
structure will look like this:
{
"queries": {
"TeamsDocument": "{orgName: params.orgName, pageSize: 10}"
}
}
Generated Loaders
The generator function uses this meta-information to create loaders for both server and client:
export const loaders = ({ params, context }) => {
const { apolloClient: client } = context;
const queries = { GetTeamsDocument: { orgName: params.orgName, pageSize: 10 } };
const organizationTeamsQuery = client.query({
query: GetTeamsDocument,
variables: queries['GetTeamsDocument'],
fetchPolicy: __SERVER__ ? 'network-only' : 'cache-first',
});
return {
data: {
organizationTeamsQuery
}
};
}
const clientLoader = async ({ params, serverLoader }) => {
const client = window.__APOLLO_CLIENT__;
try {
const getKey = (documentName) => camelCase(documentName).replace('Document', '');
const queries = { GetTeamsDocument: { orgName: params.orgName, pageSize: 10 } };
const queryKeys = ['TeamsQuery'];
let shouldCallServerLoader = false;
let response = {};
let cachedData, cacheKey;
cachedData = client.cache.readQuery({
query: GetTeamsDocument,
variables: queries['GetTeamsDocument'],
});
cacheKey = getKey('GetTeamsDocument');
if (!cachedData) {
shouldCallServerLoader = true;
}
if (cachedData && cachedData[cacheKey]) {
response[queryKeys[0]] = Promise.resolve(cachedData[cacheKey]);
}
if (!shouldCallServerLoader) return response;
const serverData = await serverLoader();
let queryKey = queryKeys[0];
if (!serverData[queryKey].then) {
return;
}
serverData[queryKey].then(({ data }) => {
client.cache.writeQuery({
query: GetTeamsDocument,
variables: queries['GetTeamsDocument'],
data,
});
});
return serverData;
} catch (err) {
console.error('Error in clientLoader', err);
}
}
This approach ensures that by the time the component requests the data, it is already available in the Apollo Cache, reducing redundancy and improving performance.
Related Topics
- For detailed parameter generation, see Query Params Generator
- For automated loader generation, see Generated Data Loaders
- For authentication integration, see Authentication and Authorization
Back to Index | Previous: Advanced Configurations | Next: Query Parameters Generator