React Custom useRequest Hook 导致内存泄漏
React Custom useRequest Hook causes MemoryLeak
我正在开发一个使用 自定义挂钩 useRequest
从服务器获取数据的项目。
实现是
const useRequest = ({ url }) => {
const [isLoading, setIsLoading] = React.useState(true);
const [error, setError] = React.useState(null);
const [apiData, setApiData] = React.useState({});
React.useEffect(() => {
const abortController = new AbortController();
fetch(url, {
headers: headers,
signal: abortController.signal,
})
.then((res) => res.json())
.then((data) => {
setIsLoading(false);
if (data.status_message) {
throw Error(data.status_message);
}
setApiData(data);
})
.catch((err) => {
setError(err);
setIsLoading(false);
});
return function cleanup() {
abortController.abort();
};
}, [url]);
return { isLoading, apiData, error };
};
export default useRequest;
我不知道为什么,但有时 它会抛出内存泄漏错误。 有人可以帮助解释为什么会这样吗?
我使用 useRequest
挂钩的组件:
1) ItemInfo 组件-
function Item() {
const { id } = useParams();
const { path } = useRouteMatch();
const type = path.split("/")[1];
const { isLoading, apiData, error } = useRequest({
url: request.getItemData(id, type),
});
if (error) return <NotFound error={error} />;
if (isLoading) return <Loader />;
const RowComp = withRow(Row);
return (
<div className="itemInfo">
{apiData && (
<>
<Banner data={apiData} />
<div className="itemInfo__wrapper">
<div className="itemInfo__overview">
<h2>Overview</h2>
<p>{apiData.overview}</p>
</div>
<Details details={apiData} />
<RowComp title="Cast" url={request.getCast(type, id)} />
{type === "movie" && apiData.belongs_to_collection && (
<RowComp
url={request.getCollection(apiData.belongs_to_collection.id)}
title="Collections"
/>
)}
{type === "tv" && apiData.seasons && (
<Row results={apiData.seasons} title="Seasons" />
)}
<RowComp
url={request.getRecommendations(id, type)}
title="Recommendations"
/>
</div>
</>
)}
</div>
);
}
export default Item;
2)一个HOC
function withRow(WrappedComponent) {
const HOC = ({ url, title }) => {
const { isLoading, apiData } = useRequest({ url });
const results = apiData.results || apiData.parts || apiData.cast;
return (
<>
{isLoading && <Loader />}
{results && <WrappedComponent results={results} title={title} />}
</>
);
};
HOC.propTypes = {
url: PropTypes.string,
title: PropTypes.string,
};
return HOC;
}
HOC组件主要记录错误,但有时ItemInfo组件也会记录Memory Leak错误
提前致谢。
事情是这样的:
1.) 组件卸载。
2.) 效果清理发生(紧随其后,同步),并且 abortController.abort();
被调用。从现在开始,不会在组件上调用 setState
。
3.) fetch(...)
或 res.json()
(?) 抛出异常,Promise 被拒绝
4.) 在微任务中,.catch
回调运行,setError
和 setIsLoading
被调用。由于该组件不再存在,因此出现了您看到的错误。
在我看来清理获取应该是无声的,所以 AbortError
s 应该被抑制:
.catch(error => {
// If the component is cleaned up, and the fetch() is aborted, silently stop as nobody is listening to our error anyways
if(error.name === "ABORT_ERR") return;
// In other cases, raise error to component:
});
我正在开发一个使用 自定义挂钩 useRequest
从服务器获取数据的项目。
实现是
const useRequest = ({ url }) => {
const [isLoading, setIsLoading] = React.useState(true);
const [error, setError] = React.useState(null);
const [apiData, setApiData] = React.useState({});
React.useEffect(() => {
const abortController = new AbortController();
fetch(url, {
headers: headers,
signal: abortController.signal,
})
.then((res) => res.json())
.then((data) => {
setIsLoading(false);
if (data.status_message) {
throw Error(data.status_message);
}
setApiData(data);
})
.catch((err) => {
setError(err);
setIsLoading(false);
});
return function cleanup() {
abortController.abort();
};
}, [url]);
return { isLoading, apiData, error };
};
export default useRequest;
我不知道为什么,但有时 它会抛出内存泄漏错误。 有人可以帮助解释为什么会这样吗?
我使用 useRequest
挂钩的组件:
1) ItemInfo 组件-
function Item() {
const { id } = useParams();
const { path } = useRouteMatch();
const type = path.split("/")[1];
const { isLoading, apiData, error } = useRequest({
url: request.getItemData(id, type),
});
if (error) return <NotFound error={error} />;
if (isLoading) return <Loader />;
const RowComp = withRow(Row);
return (
<div className="itemInfo">
{apiData && (
<>
<Banner data={apiData} />
<div className="itemInfo__wrapper">
<div className="itemInfo__overview">
<h2>Overview</h2>
<p>{apiData.overview}</p>
</div>
<Details details={apiData} />
<RowComp title="Cast" url={request.getCast(type, id)} />
{type === "movie" && apiData.belongs_to_collection && (
<RowComp
url={request.getCollection(apiData.belongs_to_collection.id)}
title="Collections"
/>
)}
{type === "tv" && apiData.seasons && (
<Row results={apiData.seasons} title="Seasons" />
)}
<RowComp
url={request.getRecommendations(id, type)}
title="Recommendations"
/>
</div>
</>
)}
</div>
);
}
export default Item;
2)一个HOC
function withRow(WrappedComponent) {
const HOC = ({ url, title }) => {
const { isLoading, apiData } = useRequest({ url });
const results = apiData.results || apiData.parts || apiData.cast;
return (
<>
{isLoading && <Loader />}
{results && <WrappedComponent results={results} title={title} />}
</>
);
};
HOC.propTypes = {
url: PropTypes.string,
title: PropTypes.string,
};
return HOC;
}
HOC组件主要记录错误,但有时ItemInfo组件也会记录Memory Leak错误 提前致谢。
事情是这样的:
1.) 组件卸载。
2.) 效果清理发生(紧随其后,同步),并且 abortController.abort();
被调用。从现在开始,不会在组件上调用 setState
。
3.) fetch(...)
或 res.json()
(?) 抛出异常,Promise 被拒绝
4.) 在微任务中,.catch
回调运行,setError
和 setIsLoading
被调用。由于该组件不再存在,因此出现了您看到的错误。
在我看来清理获取应该是无声的,所以 AbortError
s 应该被抑制:
.catch(error => {
// If the component is cleaned up, and the fetch() is aborted, silently stop as nobody is listening to our error anyways
if(error.name === "ABORT_ERR") return;
// In other cases, raise error to component:
});