【问题标题】:useEffect cleanup function in reactreact中的useEffect清理功能
【发布时间】:2021-01-05 08:56:02
【问题描述】:

我收到此警告“无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要解决此问题,请在 useEffect 清理函数中取消所有订阅和异步任务。'

代码

 const [photo, setPhoto] = useState([]);
 useEffect(() => {
 fetch('/mypost', {
  headers: {
    cookie: 'access_token',
  },
})
  .then((res) => res.json())
  .then((data) => {
    setPhoto(data.mypost);
  });
}, []);

数据已获取,但我不知道要在清理中添加什么。有什么建议吗?

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    问题

    问题是获取请求已解决,但组件已卸载(出于某种原因),因此现在无法进行状态更新。

    解决方案

    您需要使用Abort Controller 来取消正在进行的请求。如果组件卸载,效果清理函数会取消获取请求。

    useEffect(() => {
      const controller = new AbortController(); // <-- create controller
      const { signal } = controller; // <-- get signal for request
    
      fetch('/mypost', {
        headers: {
          cookie: 'access_token',
        },
        signal, // <-- pass signal with options
      })
        .then((res) => res.json())
        .then((data) => {
          setPhoto(data.mypost);
        });
    
      return () => controller.abort(); // <-- return cleanup function to abort
    }, []);
    

    注意:abort() 被调用时,fetch() 承诺会以一个拒绝 AbortError.

    您可能需要在某处捕捉到此承诺拒绝。您可以将.catch 块附加到 Promise 链。

      fetch('/mypost', {
        headers: {
          cookie: 'access_token',
        },
        signal, // <-- pass signal with options
      })
        .then((res) => res.json())
        .then((data) => {
          setPhoto(data.mypost);
        })
        // catch any rejected fetch promises (including aborted fetches!)
        .catch(console.error);
    

    【讨论】:

    • 这是部分解决方案,因为中止控制器仅拒绝第一个 fetch 承诺。如果 unmounting 在它完成之后调用,但在最后一个 Promise 链完成之前,当组件已经卸载时,setPhoto 将被调用。
    【解决方案2】:

    Generic JSON fetch demo

    import React, {useState} from "react";
    import { useAsyncEffect } from "use-async-effect2";
    import cpFetch from "cp-fetch";
    
    export default function TestComponent(props) {
      const [photo, setPhoto] = useState([]);
    
      useAsyncEffect(
        function* () {
          const response = yield cpFetch('/mypost');
          setPhoto((yield response.json()).mypost);
        },
        []
      );
    
      return <div></div>;
    }
    

    【讨论】:

      【解决方案3】:

      试试下面的代码:

       useEffect(() => {
      let isMounted = true;
       fetch('/mypost', {
        headers: {
          cookie: 'access_token',
        },
      })
        .then((res) => res.json())
        .then((data) => {
          if (isMounted)  setPhoto(data.mypost);
        });
      
      //cleanup function
      rreturn () => { isMounted = false };
          
      }, []);
      

      【讨论】:

        猜你喜欢
        • 2021-02-07
        • 1970-01-01
        • 2021-12-24
        • 2021-04-09
        • 2021-10-31
        • 1970-01-01
        • 2020-02-16
        • 2020-08-27
        • 1970-01-01
        相关资源
        最近更新 更多