管理对同一个 Apollo 突变的多次调用

Wes*_*ton 3 javascript apollo reactjs graphql

所以看看文档中的 Apollo useMutation 示例https://www.apollographql.com/docs/react/data/mutations/#tracking-loading-and-error-states

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>
    );
  });
}
Run Code Online (Sandbox Code Playgroud)

这似乎有一个重大缺陷(imo),更新任何待办事项都会显示每个待办事项的加载状态,而不仅仅是具有待处理突变的待办事项。

在此处输入图片说明

这似乎源于一个更大的问题:无法跟踪对同一突变的多次调用的状态。因此,即使我确实只想显示实际加载的待办事项的加载状态,也没有办法做到这一点,因为我们只有“正在加载”的概念,而不是“正在为待办事项 X 加载”的概念。

除了在 Apollo 之外手动跟踪加载状态之外,我能看到的唯一合适的解决方案是拆分一个单独的组件,使用它来呈现每个 Todo,而不是直接在 Todos 组件中使用该代码,并让这些组件各自初始化自己的突变。我不确定我认为这是一个好还是坏的设计,但在任何一种情况下,我都不觉得我应该改变组件的结构来实现这一点。

这也扩展到错误处理。如果我更新一个待办事项,然后在第一个更新正在进行时更新另一个会怎样。如果第一次调用出错,那在data返回的 from 中useMutation是否可见?第二个电话呢?

有没有原生的 Apollo 方法来解决这个问题?如果没有,是否有比我提到的更好的处理方法?

代码沙盒:https : //codesandbox.io/s/v3mn68xxvy

Dan*_*den 6

诚然,应该重写文档中的示例以使其更加清晰。它还存在许多其他问题。

useQueryuseMutation挂钩仅设计用于在时间跟踪单个操作的装载,错误和结果状态。操作的变量可能会改变,可能会重新获取或附加到 using fetchMore,但最终,您仍然只是在处理那个操作。您不能使用单个钩子来跟踪多个操作的单独状态。为此,您需要多个钩子。

对于这样的表单,如果提前知道输入字段,那么您可以将钩子拆分为同一组件中的多个:

const [updateA, { loading: loadingA, error: errorA }] = useMutation(YOUR_MUTATION)
const [updateB, { loading: loadingB, error: errorB }] = useMutation(YOUR_MUTATION)
const [updateC, { loading: loadingC, error: errorC }] = useMutation(YOUR_MUTATION)
Run Code Online (Sandbox Code Playgroud)

如果您正在处理可变数量的字段,那么我们必须将此逻辑分解为一个单独的逻辑,因为我们无法在循环中声明钩子。这不是 Apollo API 的限制,而只是钩子本身背后的魔法的副作用。

const ToDo = ({ id, type }) => {
  const [value, setValue] = useState('')
  const options = { variables = { id, type: value } }
  const const [updateTodo, { loading, error }] = useMutation(UPDATE_TODO, options)
  const handleChange = event => setValue(event.target.value)

  return (
    <div>
      <p>{type}</p>
      <form onSubmit={updateTodo}>
        <input
          value={value}
          onChange={handleChange}
        />
        <button type="submit">Update Todo</button>
      </form>
    </div>
  )
}

// back in our original component...

return data.todos.map(({ id, type }) => (
  <Todo key={id} id={id} type={type] />
))

Run Code Online (Sandbox Code Playgroud)