Custom hook rerender does not trigger component to rerender

57 Views Asked by At

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?

0

There are 0 best solutions below