【发布时间】:2020-03-13 05:35:10
【问题描述】:
因此,请查看文档 https://www.apollographql.com/docs/react/data/mutations/#tracking-loading-and-error-states 中的 Apollo useMutation 示例
function Todos() {
...
const [
updateTodo,
{ loading: mutationLoading, error: mutationError },
] = useMutation(UPDATE_TODO);
...
return data.todos.map(({ id, type }) => {
let input;
return (
<div key={id}>
<p>{type}</p>
<form
onSubmit={e => {
e.preventDefault();
updateTodo({ variables: { id, type: input.value } });
input.value = '';
}}
>
<input
ref={node => {
input = node;
}}
/>
<button type="submit">Update Todo</button>
</form>
{mutationLoading && <p>Loading...</p>}
{mutationError && <p>Error :( Please try again</p>}
</div>
);
});
}
这似乎有一个重大缺陷(imo),更新任何待办事项都会显示每个待办事项的加载状态,而不仅仅是具有待处理突变的待办事项。
这似乎源于一个更大的问题:无法跟踪对同一突变的多次调用的状态。因此,即使我确实只想显示实际加载的待办事项的加载状态,也没有办法做到这一点,因为我们只有“正在加载”而不是“正在加载待办事项 X”的概念。
除了在 Apollo 之外手动跟踪加载状态之外,我能看到的唯一不错的解决方案是拆分一个单独的组件,使用它来渲染每个 Todo,而不是将代码直接放在 Todos 组件中,并让这些组件各自初始化它们的自己的突变。我不确定我认为这是一个好还是坏的设计,但无论哪种情况,我都不觉得我应该改变组件的结构来实现这一点。
这也延伸到错误处理。如果我更新一个待办事项,然后在第一次更新正在进行时更新另一个呢?如果第一次调用出错,那在从useMutation 返回的data 中是否可见?第二个电话呢?
有本地 Apollo 方法来解决这个问题吗?如果没有,是否有处理这个问题的选项可能比我提到的更好?
【问题讨论】:
-
我对你的问题有点困惑。并不是说 apollo 没有唯一/多个加载状态,而是您的代码只有一个
mutationLoading。声明你传递给你的待办事项。相同的状态会传递给它们,所以即使 apollo 有你想要的东西,你的代码仍然不会使用它。它至少必须是loadingId === id之类的东西。无论如何,通过在项目级别而不是列表级别调用useMutation可以完全解决您的问题。这不是一种解决方法,它是完全理智的解决方案 -
另一方面,apollo 确实会跟踪正在运行的查询。因此您可以将
isLoading与将哪个变量传递给突变的知识结合起来,尽管我认为这是一个更糟糕的解决方案 -
我知道当前代码不会利用从 useMutation 返回的任何每个项目的状态。我知道你想做
loadingId === id之类的操作,但loadingId不可用。 -
至于“你可以将你的 isLoading 与传递给突变的变量的知识结合起来”,如果同时进行多个突变,那将如何工作?如果我不确切知道哪些突变实际上是
loading,loading将毫无意义。 -
至于将突变推到项目级别,我不同意这是一个理智的解决方案,但它确实有缺点。也就是说,父组件失去了对其项目加载状态的任何了解。假设我想在
Todos组件中显示待办事项的加载状态(出于某种原因),我要么失去这种能力,要么需要向Todo组件添加某种onLoading回调,并且仍然手动跟踪Todos中的加载状态。
标签: javascript reactjs graphql apollo