gpt4 book ai didi

ajax - 在自定义 React 钩子(Hook)中的 AJAX 函数后清理

转载 作者:行者123 更新时间:2023-12-04 10:15:27 24 4
gpt4 key购买 nike

我编写了一个自定义的 React 钩子(Hook),它使用 jQuery 通过 AJAX 从给定的 URL 获取结果(这是在遗留应用程序的上下文中,因此需要使用 jQuery 进行 AJAX),其 API 的灵感来自 axios-hooks .代码如下(注意它包括 Flow 注释):

//@flow
import { useCallback, useState, useEffect } from "react";
import type { jquery } from "jquery";

declare var $: jquery;

function useAjaxGet(url: string) {
const [loading, setLoading] = useState(true);
const [data, setData] = useState(null);
const [error, setError] = useState(null);

const fetchData = useCallback(() => {
setLoading(true);
$.ajax({
type: "GET",
url: url,
dataType: "json"
}).done((data) => {
setData(data);
setLoading(false);
setError(false);
}).fail(() => {
setLoading(false);
setError(true);
});
}, [url]);

useEffect(() => {
fetchData();
}, [url, fetchData]);

return [{
data: data,
loading: loading,
error: error
}, fetchData];
}

export default useAjaxGet;

现在,这适用于简单的应用程序,但迟早会引发以下错误:
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.

我理解我必须返回一个清理函数,并且不这样做会导致内存泄漏。但是,我很难理解在这种情况下我能做些什么来清除它。任何人都可以对此有所了解吗?

最佳答案

有很多方法可以清理组件。主要概念很简单:你不应该更新 umount react 元素中的状态 .

解决方案 1:避免使用 isMount 手动更新状态多变的

  const fetchData = useCallback(() => {
let isMounted = true
setLoading(true);
$.ajax({
type: "GET",
url: url,
dataType: "json"
}).done((data) => {
// Before updating the state, check if the element has been unmounted while waiting
if (!isMounted) {
return;
}
setData(data);
setLoading(false);
setError(false);
}).fail(() => {
// Same, check if the element has been unmounted while waiting
if (!isMounted) {
return;
}
setLoading(false);
setError(true);
});
// Cleanup function
return () => {
isMounted = false;
};
}, [url]);

您可以在 Facebook's Relay Docs 上查看此解决方案.

Demo using isMounted

解决方案2:取消卸载生命周期的请求(AJAX jQuery)

这将避免执行所有的 promise 回调。干净多了! (以下示例使用 jQuery v3)

  useEffect(() => {
const xhr = new window.XMLHttpRequest();
$.ajax({
url: url,
xhr: function() {
return xhr;
}
})
.then(response => {
setState(response);
})
.catch(error => {
console.log(error);
});
return () => {
xhr.abort(); // Cancel the request on unmount
};
}, [url]);

Demo using Ajax request cancel

解决方案3:取消卸载生命周期(获取)的请求

与解决方案 2 相同,但使用 fetch , 因为使用率更高。

  useEffect(() => {
const controller = new AbortController();
const { signal } = controller;
fetch(url, { signal })
.then(res => res.json())
.then(response => {
setState(response);
})
.catch(error => {
console.log(error);
});
return () => {
controller.abort();
};
}, [url]);

Demo using AbortController

关于ajax - 在自定义 React 钩子(Hook)中的 AJAX 函数后清理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61083727/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com