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
         },})
  }
/>

我尝试过的一些事情:

  • 各种缓存策略
  • 不对选项使用对象,而是将每个可能的选项定义为不同的变量

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

解决方法

我猜只有 pick 被称为 ...

... 因为对于 <MyBytton/> 没有 props 改变,没有 onPick 重新定义 - 总是使用的第一个处理程序定义(从第一次渲染)和 options 状态从同一时间开始。 ..

尝试将所有(optionspickrefetch)作为直接属性传递以强制重新渲染和处理程序重新定义:

<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} />