如何将 react-query useMutation 与多部分文件上传一起使用?

How to use react-query useMutation with a multi-part file upload?

我正在尝试在 Drupal 后端上使用带有 Ionic React webapp 的 react-query。我有一个 React 表单(使用 react-hook-form),让用户可以选择将图像附加到他们的用户帐户。

Ionic 通过 JSON:API 与 Drupal 交互,而 Drupal 的 JSON:API 要求先上传文件,然后将文件附加到用户帐户,所以我需要两个突变。

我的问题是:如何实现这两个突变以便上传文件,然后,如果成功,我使用第二个突变更新用户帐户,如果上传不成功,我显示错误?

目前我的代码如下所示:

AddPhoto.tsx

  const onSubmit = async (userData: JsonFormUser) => {
    if (userData.photoType === 'other') {
      const myJsonData : JsonDataUserPhotoOther = {
        data: {
          id: userObject.id,
          type: 'user',
          attributes: {
            photoType: userData.photoType,
            photoName: userData.photoName,
          },
        },
      };

      // Upload the new photo.
      if (imageSrc && !imageSrc.includes(baseUrl)) {
        const myCroppedImgBlob = await getCroppedImg(
          imageSrc,
          croppedAreaPixels,
        );
        mutatePhotoFile.mutate(myCroppedImgBlob);
        // Todo: Find a way to run this only if the mutate is successful.
        mutateUser.mutate(myJsonData);

所以我想做的是 运行 mutateUser 如果 mutatePhotoFile 成功。

这是mutatePhotoFile

  const mutatePhotoFile = useMutation(
    (
      myImageBlob: string,
    ) => postFileBlobWithUserAuth(
      `${postUserUrl(userObject.id)}/field_ref_image`, myImageBlob,
    ), {
      onSuccess: (response: ResponseMutatePhoto) => {
        userDispatch({ type: 'setPhoto', payload: response });
      },
      onError: () => {
        setShowFileAlert(true);
      },
    },
  );

我试图在 mutatePhotoFileonSuccess 中调用 mutateUser,但我无法访问 myJsonData 变量,因为它的范围是 onSubmit函数。

然后我尝试使用 useState 来存储 myJsonData,但是 mutatePhotoFileuseState 更新之前完成解析。

我猜 Javascript 中可能有一种我不知道的处理此问题的模式。

总而言之,

  1. 用户点击提交按钮。
  2. 我触发了一个将文件上传到 Drupal 的反应查询突变。
  3. 如果有错误,我会显示给用户。如果没有错误,我会立即触发另一个更新用户帐户的突变。

我可以使用什么样的模式来实现它?

您可以使用 mutate 函数上也可用的 onSuccess 回调,以便您可以访问 myJsonData:

mutatePhotoFile.mutate(
  myCroppedImgBlob, {
    onSuccess: () => mutateUser.mutate(myJsonData)
  }
)

或者,您可以使用 mutateAsync 来链接承诺,但您需要手动捕获错误(因为 react-query 只对 mutate 执行此操作 - 否则您将得到未处理的承诺拒绝) :

try {
  await mutatePhotoFile.mutateAsync()
  mutateUser.mutateAsync(myJsonData);
}
catch(e) {...}