【问题标题】:Apollo useLazyQuery hook uses old variables when refetching (instead of new vars)Apollo useLazyQuery 钩子在重新获取时使用旧变量(而不是新变量)
【发布时间】:2021-09-03 17:22:52
【问题描述】:

我的数据库存储了一个项目列表。我编写了一个查询,每次单击按钮时从列表中随机返回一个项目。我使用 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
         },
     })
  }
/>

我尝试过的一些事情:

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

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

【问题讨论】:

  • 您是否尝试过fetch-policy = network-only 也请分享您的代码,说明您如何获得选项
  • 如果'它们在客户端不同'(检查网络请求正文?)那么根本不是客户端问题?
  • @MuhammadBilalBangash 选项被传递给我发布的“onPick”处理程序。我可以在调用惰性查询之前跟踪它,并查看“选项”对象中的值是否正确更改。例如,根据我选择的按钮,它可能是 { minimum: 5000 } 或 { minimum: 4000, maximum: 8000 }。我可以正确看到这些更新,但无论它们是什么,我在解析器中追踪的值将始终是第一次调用惰性查询时的任何选项。
  • @xadm 请求负载中的变量始终是第一次调用惰性查询时的变量。我可以在调用惰性查询函数之前在客户端上追踪它们,它们会改变,但是当请求发出时,它们与第一次调用时发送的相同。所以问题似乎在于将新值传递给惰性查询函数没有效果。
  • @MuhammadBilalBangash 我已经尝试了所有缓存策略。他们已经对 -responses-get back 做了正确的事情(换句话说,no-cache 会导致新请求,cache-first 只会获取缓存的响应)。问题是发送到服务器的变量“卡住”,尽管它们在传递给惰性函数时有所不同。

标签: reactjs graphql apollo


【解决方案1】:

我猜只有pick 被称为...

...因为&lt;MyBytton/&gt; 没有道具更改,没有重新定义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
         },
     })
  }
/>

... 或 [更好] 在将处理程序传递给 &lt;MyButton/&gt; 之前定义处理程序:

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

【讨论】:

  • 我不能这样做,因为在单击按钮之前我没有选项。这就是我使用惰性处理程序的原因。该应用可以在“onPick”触发之前多次重新渲染。
  • ... 这正是您所需要的(useCallback 是为之设计的)...处理程序仅在依赖项更改时更新(不是在每次渲染时)-options 是依赖项,将在需要时成为实际......只需尝试,日志就会说出真相
猜你喜欢
  • 2021-01-30
  • 2020-05-18
  • 2019-12-20
  • 2019-11-30
  • 2015-02-11
  • 2019-08-30
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
相关资源
最近更新 更多