为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕哥6287543 2024-01-18 16:10:53
当我使用 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;
查看完整描述

2 回答

?
青春有我

TA贡献1784条经验 获得超8个赞

我想我应该展示如何将其提取到自定义挂钩中。


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;


查看完整回答
反对 回复 2024-01-18
?
杨__羊羊

TA贡献1943条经验 获得超7个赞

您可以React.useRef为此使用:


在您的组件中:


const hasUnmounted = React.useRef(false);


React.useEffect(() => {


 // maybe you have your side effects here, so you can use the boolean to avoid 

 // state updates when the component is unmounted


 if(!hasUnmounted.current) {

  // do state update 

 }

 return () => {

  hasUnmounted.current = true;

 }

}, [])

React.useRef适合解决这个问题,因为它与更改组件的状态非常不同,这有点像类组件中的实例变量,更改它不会触发重新渲染。


查看完整回答
反对 回复 2024-01-18
  • 2 回答
  • 0 关注
  • 81 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信