首页 > 解决方案 > Apollo useLazyQuery 钩子在重新获取时使用旧变量(而不是新变量)

问题描述

我的数据库存储项目列表。我编写了一个查询,每次单击按钮时从列表中随机返回一个项目。我使用 useLazyQuery 并调用返回的函数来执行查询,它工作正常。我可以在随后的按钮按下时调用 refetch 函数,它会正确返回另一个随机项目。

当我尝试将变量传递给查询时,问题就来了。我想为查询提供不同的标准以定制随机选择的方式。我传递给第一次调用的任何变量都会在每次重新获取时重复,即使它们已经改变。我可以追踪它们在客户端上是不同的,但解析器会追踪以前的变量。

// My query
const PICK = gql`
  query Pick($options: PickOptionsInput) {
    pick(options: $options) {
      title
    }
  }
`;

// My lazy hook
const [pick, { data, refetch }] = useLazyQuery(PICK, {
    fetchPolicy: "no-cache",
  });


// My button
<MyButton
  onPick={(options) =>
     (refetch || pick)({ // Refetch unless this is the first click, then pick
         variables: {
            options      // Options is a custom object of data used to control the pick
         },
     })
  }
/>

我尝试过的一些事情:

我真的很难过。似乎文档说如果在重新获取时提供了新变量,则应该使用它们。我不认为缓存策略是相关的......每次调用我都会得到新的结果,只是输入变量是陈旧的。

标签: reactjsgraphqlapollo

解决方案


我猜只有pick被称为...

...因为<MyBytton/>没有道具更改,没有onPick重新定义 - 始终使用的第一个处理程序定义(从第一次渲染开始)和同时options的状态......

尝试将所有 ( options,pickrefetch) 作为直接道具传递以强制重新渲染和处理程序重新定义:

<MyButton
  options={options}
  pick={pick}
  refetch={refetch}
  onPick={(options) =>
     (refetch || pick)({ // Refetch unless this is the first click, then pick
         variables: {
            options      // Options is a custom object of data used to control the pick
         },
     })
  }
/>

...或[更好]在将处理程序传递给之前定义处理程序<MyButton/>

const pickHandler = useCallback( 
  (options) => {
     if(refetch) {
       console.log('refetch', options);
       refetch( { variables: { options }});
     } else {
       console.log('pick', options);
       pick( { variables: { options }});
     }
  },
  [options, pick, refetch]
);

<MyButton onPick={pickHandler} />

推荐阅读