I have an application that uses React, Typescript, and Apollo. Apollo has built-in support for caching. This caching is used within the application in place of state management.
Within that context, I created a custom hook that checks the apollo cache and if the data is missing it fires the query using useQuery
from apollo/client
.
Here is the custom hook,
import {
RESOURCE_QUERY,
ResourceFragment,
Resource
} from '@custom/services';
import { useApolloClient, useQuery } from '@apollo/client';
import { useDebugValue } from 'react';
export const useResource = ({ id }: { id: string }) => {
const client = useApolloClient();
const cached = client.readFragment({
id: `Resource:${id}`,
fragment: ResourceFragment,
fragmentName: 'ResourceFields'
});
const { loading, error } = useQuery(RESOURCE_QUERY, {
variables: {
findOneResourceId: id
},
skip: !!cached || !id
});
// ** It is placed for debugging purposes, output will be shared at the end of the question.
console.log('useResource', loading);
return {
data: cached,
loading,
error
};
};
Here is how it is used in the component
import { isValidElement } from 'react';
import { useParams } from 'react-router';
import { useResource } from './use-resource';
export function ResourceGuard({ children }: { children: React.ReactNode }) {
const { resourceId } = useParams<{ resourceId: string }>();
const { data, error, loading } = useResource({
id: resourceId
});
// ** It is placed for debugging purposes, output will be shared at the end of the question.
console.log('ResourceGuard', loading);
if (loading) {
return <div>Loading...</div>
}
if (!loading && error) {
return <div>Not found</div>
}
return isValidElement(children) ? children : <>{children}</>;
}
Here is the console output:
useResource true
useResource true
useResource true
useResource true
useResource false
useResource false
useResource false
ResourceGuard false
useResource false
useResource false
useResource false
useResource false
useResource false
useResource false
useResource false
So the problem is as you can see the hook indicates the loading state however it does not force the component to rerender.
What could be the issue here?