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 回调运行,setErrorsetIsLoading 被调用。由于该组件不再存在,因此出现了您看到的错误。

在我看来清理获取应该是无声的,所以 AbortErrors 应该被抑制:

.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:
});