我有下面的代码
const [status, statusSetter] = useState({ isAuthenticated: false });
useEffect(() => {
let didCancel = false;
async function fetchMyAPI() {
if (!didCancel) {
let response = (await axios.get('api/auth/getuserstatus')).data;
statusSetter(response);
}
}
fetchMyAPI();
return () => {
didCancel = true;
}
}, []);
我尝试将 didcancel
实现为 userEffects 的一种清理形式,但它不起作用。我收到以下错误:
“无法对卸载的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。”
我应该把什么东西清理干净?
答案 0 :(得分:1)
那个变量应该只阻止调用 statusSetter:
async function fetchMyAPI() {
let response = (await axios.get('api/auth/getuserstatus')).data;
!didCancel && statusSetter(response);
}
但是,基本上,这是一个黑客,因为这种方法不会清理任何东西。我们保留无用的后台工作,只是不更改结果中的组件状态。我们应该以某种方式中止挂起的 get 请求。
通过自定义的实验性钩子,我们可以编写可自动取消的异步例程。例如,如果在获取 (Live demo to play) 时卸载组件,则以下 json 请求将自动中止:
import React, { useState } from "react";
import { useAsyncEffect, E_REASON_UNMOUNTED } from "use-async-effect2";
import cpAxios from "cp-axios";
export default function TestComponent(props) {
const [text, setText] = useState("");
const cancel = useAsyncEffect(function* () {
const response = yield cpAxios(props.url);
setText(`Success: ${JSON.stringify(response.data)}`);
},
[props.url]
);
return (...)
}
答案 1 :(得分:0)
此代码应该适合您:
WITH product_ids AS (
WITH RECURSIVE cte AS (
( -- parentheses required
SELECT product_id
FROM tickers
ORDER BY 1
LIMIT 1
)
UNION ALL
SELECT l.*
FROM cte c
CROSS JOIN LATERAL (
SELECT product_id
FROM tickers t
WHERE t.product_id > c.product_id -- lateral reference
ORDER BY 1
LIMIT 1
) l
)
TABLE cte
)
SELECT
product_id,
(SELECT (MAX(trade_id) - MIN(trade_id) + 1) FROM tickers WHERE product_id = product_ids.product_id) AS ticker_count,
(SELECT MIN(time) FROM tickers WHERE product_id = product_ids.product_id) AS min_time,
(SELECT MAX(time) FROM tickers WHERE product_id = product_ids.product_id) AS max_time
FROM product_ids
ORDER BY ticker_count DESC
答案 2 :(得分:0)
使用 axios,您可以这样做:
useEffect(() => {
const source = axios.CancelToken.source();
fetchMyAPI(source);
return () => {
source.cancel();
};
}, []);
然后在获取函数中
const fetchMyAPI = async (source) => {
try {
const response = await axios({
cancelToken: source.token,
});
} catch (err) {
if (!axios.isCancel(err)) {
// TO DO...
}
}
};