Повторная выборка клиента Apollo () не обновляет кэш, когда ответ от сервера — пустой список

#caching #react-apollo #apollo-client #apollo-cache-inmemory

#кэширование #реагировать-apollo #apollo-client #apollo-cache-inmemory

Вопрос:

Я использую refetch() всякий раз, когда переменные useQuery изменяются для фильтрации списка. Каждый раз, когда изменяется переменная prop, она извлекает результаты в соответствии с фильтрами, когда результаты с сервера являются пустым списком [] , метод refetch() возвращает кэшированные результаты, а не пустой список [] .

 const { loading, error, data, fetchMore, refetch } = useQuery(Users, {
    variables: {
      userNumber: userNum,
    },
  });

useEffect(() => {
    if (userNum){
      refetch();
    } 
    }, [userNum]);
  

Таким образом, он извлекает обновленный результат каждый раз, когда пользовательский реквизит изменяется со списком пользователей, у которых есть этот номер пользователя. однако, если список пользователей, возвращенных с сервера, пуст (поскольку ни у одного пользователя нет этого номера), я вижу предыдущие кэшированные результаты вместо пустого списка.

Я пробовал

 fetchPolicy: 'cache-and-network', 
nextFetchPolicy: 'cache-first', 
  

и все равно получаем кэшированные результаты вместо пустого списка.

Я также попробовал merge() в typePolicies, и это сработало! Однако, когда я применяю relayStylePagination, он снова извлекает кэшированные результаты, а не пустой список.

 uri: 'http://localhost:5000/graphql',
cache: new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        devices: relayStylePagination(),
        merge(existing = {}, incoming) {
          return { ...existing, ...incoming };
        },
      },
    },
  },
}),
});
  

Я также пробовал с ключевыми полями и снова работает, кэш обновляется, когда сервер возвращает пустой список, однако нумерация страниц реле не работает. Единственный способ заставить ретрансляционную разбивку на страницы работать — размещать ее только так:

 fields: {
          devices: relayStylePagination(),
        },
  

`
Мой запрос выглядит следующим образом:

  $after: ID
 $userNum: Int
 $dpiGt: String
 $dpiLt: String
) {
 users(
   after: $after
   userNumber: $userNum
   first: 30
   filter: { dpiGt: $dpiGt, dpiLt: $dpiLt }
 ) {
   edges {
     cursor
     node {
       id
       name
       userNumber
     }
   }
   pageInfo {
     endCursor
     hasNextPage
   }
 }
}
  

Сведения о системе:

 OS: macOS 10.15.4
Binaries:
Node: 12.16.1 - ~/n/bin/node
Yarn: 1.21.1 - /usr/local/bin/yarn
npm: 6.13.4 - ~/n/bin/npm
Browsers:
Chrome: 86.0.4240.80
Firefox: 81.0.1
Safari: 13.1
npmPackages:
@apollo/client: ^3.2.3 => 3.2.5
  

Комментарии:

1. Вы решили это?

Ответ №1:

Не уверен, что это решит вашу проблему, но стоит попробовать.

После изучения и прочтения документации Apollo в разделе повторная выборка я нашел это описание, которое может быть полезно для вашего варианта использования.

К счастью, объект результата перехвата useQuery предоставляет детализированную информацию о состоянии запроса через свойство NetworkStatus. Чтобы воспользоваться преимуществами этой информации, нам нужно установить для параметра notifyOnNetworkStatusChange значение true, чтобы наш компонент запроса повторно отображал, пока выполняется повторная выборка:

 import { useQuery, NetworkStatus } from '@apollo/client';

...

const { loading, error, data, fetchMore, refetch, networkStatus } = useQuery(Users, { 
    variables: {
      userNumber: userNum,
    },
     notifyOnNetworkStatusChange: true, 
  });
  

 if (networkStatus === NetworkStatus.refetch) return <div>Refetching!</div>; 
 
 ...