javascript - 无法使用获取 POST 方法对未安装的组件执行 React 状态更新

标签 javascript reactjs forms react-hooks fetch

当我使用我的 fetch post 方法时收到此警告如何取消 useEffect 清理函数中的所有订阅和异步任务。使用我的 Post 方法。

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

import React from "react";
import { useHistory } from "react-router-dom";
import { UPLOAD_PRESET, CLOUD_NAME, SERVER_API } from "../../config";

const uploadImage = async (file) => {
  const url = `https://api.cloudinary.com/v1_1/${CLOUD_NAME}/upload`;
  const formData = new FormData();
  formData.append("file", file);
  formData.append("upload_preset", UPLOAD_PRESET);

  const res = await fetch(url, {
    method: "POST",
    body: formData,
  });

  if (!res.ok) {
    throw new Error(`Can't upload image. ${res.status}`);
  }

  const data = await res.json();
  return await data.eager[0].secure_url;
};

const createAlbum = async (data) => {
  const res = await fetch(`${SERVER_API}/api/v1/albums`, {
    method: "POST",
    body: JSON.stringify(data),
    headers: {
      "Content-Type": "application/json",
    },
  });

  if (!res.ok) {
    throw new Error(`An error has occurred: ${res.status}`);
  }

  const json = await res.json();
  return json.data._id;
};

const Form = ({ file, loading, setError, album, color, children }) => {
  let history = useHistory();

  const clearError = () => setError("");

  const handleSubmit = async (e) => {
    e.preventDefault();
    clearError();
    try {
      if (!file) {
        throw new Error("Please select a file to add.");
      }

      if (!album.trim("") || !color.trim()) {
        throw new Error("Please enter all the field values.");
      }

      loading(true);

      const fileUrl = await uploadImage(file);

      const data = {
        name: album,
        bckImgUrl: fileUrl,
        color: color,
      };

      const albumId = await createAlbum(data);

      history.push(`/albums/${albumId}`);
    } catch (error) {
      setError(error.message);
    } finally {
      loading(false);
    }
  };
  return <form onSubmit={handleSubmit}>{children}</form>;
};

export default Form;

最佳答案

我同意 Ramesh 关于使用 ref 的观点。我想我会展示如何将它提取到自定义 Hook 中。

function useHasUnmountedRef() {
  const hasUnmountedRef = useRef(false);
  useEffect(() => {
    return () => {
      hasUnmountedRef.current = true;
    }
  }, []);
  return hasUnmountedRef;
}

function Form() {

  const hasUnmountedRef = useHasUnmountedRef();

  const handleSubmit = async () => {

    await asyncStuff();

    if (hasUnmountedRef.current) {
      // escape early because component has unmounted
      return;
    }

    // Thanks to the guard clause above, you can guarantee at this
    // point that your component is still mounted. You can perform
    // state updates without generating a React warning. 
    //
    // If you do another "await" however, you will need to check
    // again. Everytime you await something async, there is a chance
    // that the component could have unmounted while waiting for the
    // async stuff to complete.

  };

  return (
    <form onSubmit={handleSubmit} />
  );
}

export default Form;

关于javascript - 无法使用获取 POST 方法对未安装的组件执行 React 状态更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65438901/

相关文章:

javascript - 在浏览器中创建 bash shell 的可行性如何?

javascript - Cordova CLI 6.3.0 window.plugins 未定义

javascript - Azure AD 何时使用 API 权限与公开 API

javascript - react 失去 promise 内的 'this' 上下文

javascript - 失败的 Prop 类型 : Invalid prop `style` of type `number` supplied to `Styled(Container)` , 预期 `object`

forms - extjs文件上传进度

javascript - 是否可以将 id 添加到标签标签?

javascript - 启用安全浏览后,FB.UI 不显示缩略图

javascript - 使用关闭按钮切换 Bootstrap 选项卡

javascript - 除非选中指定数量的复选框,否则停止提交表单