我的情况有 4 个组件按此顺序相互嵌套:(Products
页面)ProductList
、、、ProductListItem
和CrossSellForm
。
Products
执行 graphql 查询(使用 urql),如下所示:
const productsQuery = `
query {
products {
id
title
imageSrc
crossSells {
id
type
title
}
}
}
`;
...
const [response] = useQuery({
query: productsQuery,
});
const { data: { products = [] } = {}, fetching, error } = response;
...
<ProductList products={products} />
products
返回一个Products
包含字段 的数组,该字段crossSells
返回一个 的数组CrossSells
。Products
向下传播到CrossSellForm
,其中包含一个返回数组的变异查询CrossSells
。
问题是,当我提交 crossSellForm 时,请求成功通过但crossSells
up inProducts
没有更新,并且 UI 反映了陈旧的数据。这仅在初始提取Products
包含 no时发生crossSells
,因此初始响应如下所示:
{
data: {
products: [
{
id: '123123',
title: 'Nice',
imageSrc: 'https://image.com',
crossSells: [],
__typename: "Product"
},
...
]
}
}
}
如果存在crossSell
,则没有问题,ui 会正确更新,响应如下所示:
{
data: {
products: [
{
id: '123123',
title: 'Nice',
imageSrc: 'https://image.com',
crossSells: [
{
id: 40,
title: 'Nice Stuff',
type: 'byVendor',
__typename: 'CrossSell'
}
],
__typename: "Product"
},
...
]
}
}
}
我在https://formidable.com/open-source/urql/docs/basics/上阅读了一些关于 urql 缓存机制的内容,据我了解,它使用文档缓存,因此它基于__typename
. 如果查询请求具有相同的__typename
内容,它将从缓存中提取它。如果mutation
发生相同的情况,__typename
它将使缓存中的所有对象无效,__typename
因此下次用户使用该对象获取对象时,__typename
它将执行网络请求而不是缓存。
我认为正在发生的情况是在初始情况下,products
但没有crossSells
表单提交成功,但Products
页面没有更新,因为没有对带有__typename
of的对象的引用CrossSell
,但在第二种情况下,它会破坏缓存并再次执行查询,刷新产品和交叉销售,并且 UI 已正确更新。
我真的很享受将 urql 钩子与 React 组件一起使用的体验,并想继续,但我不确定如何在不使用其他工具的情况下解决这个问题。
我尝试使用以下提示在表单提交时强制重新渲染:如何强制组件在 React 中使用钩子重新渲染?但它遇到了同样的问题,Products
它将再次从缓存中获取并crossSells
返回一个空数组。我考虑过将 urql 的 RequestPolicy 修改为仅网络,以及强制重新渲染,但我认为每次重新获取都会不必要地昂贵。我现在正在尝试的解决方案是将所有状态转移到 redux 中,这是一个单一的事实来源,以便任何更新crossSells
都能正确传播,尽管我确信它会起作用,但这也意味着我将换取一个标准 redux 样板的钩子给我带来了很多便利。
如何在提交表单时优雅地更新Products
with ,同时仍然使用 urql 和钩子?crossSells
CrossSellForm