React-Apollo:带变量的查询导致 UI 不再乐观

Posted

技术标签:

【中文标题】React-Apollo:带变量的查询导致 UI 不再乐观【英文标题】:React-Apollo: Query with variables causes the UI to no longer be optimistic 【发布时间】:2019-08-14 23:30:57 【问题描述】:

我正在使用 Apollo GraphQL 编写一个 React 组件(使用 React Apollo Hooks,但这没有区别)。

这是我的查询:

const  data, error, loading  = useQuery(ListContacts, 
  fetchPolicy: 'cache-and-network'
  // variables:  limit: 1000 
);

这是我的突变函数:

const createContact = useMutation(gql(mutations.createContact));
const deleteContact = useMutation(gql(mutations.deleteContact));
const updateContact = useMutation(gql(mutations.updateContact));

async function handleContactSave(contact) 
  const isEmpty = allStringFieldsAreEmptyFromContact(contact);
  const  id, ...processedContact  = replaceEmptyStringsWithNull(contact);
  const idIsInArray = includesContactWithId(id)(contacts);

  try 
    if (isEmpty) 
      if (idIsInArray) 
        await deleteContact(
          variables:  input:  id  ,
          optimisticResponse: () => ( deleteContact:  id  ),
          update: (cache,  data:  deleteContact  ) => 
            const query = ListContacts;
            const data = cache.readQuery( query );
            data.listContacts.items = data.listContacts.items.filter(
              item => item.id !== deleteContact.id
            );
            cache.writeQuery( query, data );
          
        );
      
     else 
      if (idIsInArray) 
        await updateContact(
          variables:  input:  id, ...processedContact  ,
          optimisticResponse: () => (
            updateContact:  __typename: 'Contact', id, ...processedContact 
          ),
          update: (cache,  data:  updateContact  ) => 
            const query = ListContacts;
            const data = cache.readQuery( query );
            data.listContacts.items = [
              ...data.listContacts.items.filter(
                item => item.id !== updateContact.id
              ),
              updateContact
            ];
            cache.writeQuery( query, data );
          
        );
       else 
        await createContact(
          variables:  input:  ...processedContact  ,
          optimisticResponse: () => (
            createContact: 
              __typename: 'Contact',
              id: uuid(),
              ...processedContact
            
          ),
          update: (cache,  data:  createContact  ) => 
            const query = ListContacts;
            const data = cache.readQuery( query );
            data.listContacts.items = [
              ...data.listContacts.items.filter(
                item => item.id !== createContact.id
              ),
              createContact
            ];
            cache.writeQuery( query, data );
          
        );
      
    
   catch (error) 
    console.log(error);
  

一旦我用limit 注释掉variables 键,UI 就不会再乐观地更新。注释掉它的值。这里出了什么问题?

【问题讨论】:

【参考方案1】:

writeQuery 方法也接受 variables 值。 queryvariables 的每个组合都被 Apollo 视为一个单独的查询。因此,如果一个Query 组件(或钩子)使用100 的限制,而另一个使用50 的限制,则在编写update 函数时,您需要为这两个查询调用writeQuery ,每次为variables 传入不同的值:

cache.writeQuery( query, data, variables:  limit: 100  )
cache.writeQuery( query, data, variables:  limit: 50  )

这是know limitation of the client。实际上,您需要通过本地状态跟踪变量,以便在调用 update 函数时正确调用 writeQuery。可以理解,这可能是一个巨大的麻烦。幸运的是,您可以使用apollo-link-watched-mutation 来解决此问题。

【讨论】:

以上是关于React-Apollo:带变量的查询导致 UI 不再乐观的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS/Javascript/Graphql/React-apollo:传递查询变量

Graphql,react-apollo如何在加载组件状态时将变量传递给查询

如何在 react-apollo graphql 查询中正确使用动态变量?

是否可以将变量传递给 react-apollo 的“儿童”道具?

react-apollo中动态改变查询的解决方案

在 react-apollo 中使用 refetchQueries 时使用现有变量