无法使用 fetch POST 方法对已卸载的组件执行 React 状态更新

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

警告:无法对已卸载的组件执行 React 状态更新。这是一个空操作,但它表明应用程序中存在内存泄漏。要修复此问题,请取消 useEffect 清理函数中的所有订阅和异步任务。

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;


慕哥6287543
浏览 82回答 2
2回答

青春有我

我想我应该展示如何将其提取到自定义挂钩中。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;

杨__羊羊

您可以React.useRef为此使用:在您的组件中:const hasUnmounted = React.useRef(false);React.useEffect(() => {&nbsp;// maybe you have your side effects here, so you can use the boolean to avoid&nbsp;&nbsp;// state updates when the component is unmounted&nbsp;if(!hasUnmounted.current) {&nbsp; // do state update&nbsp;&nbsp;}&nbsp;return () => {&nbsp; hasUnmounted.current = true;&nbsp;}}, [])React.useRef适合解决这个问题,因为它与更改组件的状态非常不同,这有点像类组件中的实例变量,更改它不会触发重新渲染。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript