【问题标题】:How can i solve React useEffect clean up error issue我如何解决 React useEffect 清理错误问题
【发布时间】:2021-05-27 15:43:48
【问题描述】:

useEffect 调用列表的主表数据,例如。国家,地点。 我正在使用空的依赖项列表,因此它只会在安装后加载。 但是错误表明清理没有正确完成,因此它在内存中泄漏。

这是我在控制台中看到的错误。

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.
    in CorporateBasicProfileSection (at CorporateProfilePage.js:148)
    in div (created by ForwardRef(Grid))
    in ForwardRef(Grid) (created by WithStyles(ForwardRef(Grid)))
    in WithStyles(ForwardRef(Grid)) (at GridItem.js:25)
    in GridItem (at CorporateProfilePage.js:139)
    in div (created by ForwardRef(Grid))
    in ForwardRef(Grid) (created by WithStyles(ForwardRef(Grid)))
    in WithStyles(ForwardRef(Grid)) (at GridContainer.js:23)
    in GridContainer (at CorporateProfilePage.js:138)
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.
    in CorporateManagerDetailSection (at CorporateProfilePage.js:152)
    in div (created by ForwardRef(Grid))
    in ForwardRef(Grid) (created by WithStyles(ForwardRef(Grid)))
    in WithStyles(ForwardRef(Grid)) (at GridItem.js:25)
    in GridItem (at CorporateProfilePage.js:150)
    in div (created by ForwardRef(Grid))
    in ForwardRef(Grid) (created by WithStyles(ForwardRef(Grid)))
    in WithStyles(ForwardRef(Grid)) (at GridContainer.js:23)
    in GridContainer (at CorporateProfilePage.js:138)

这是useEffect中的清理功能

企业基本资料部分

  React.useEffect(() => {
    let mounted = true;
    console.log("mountedbasic profile");
    if (mounted) {
      fetchIndustryList();
      fetchCompanyList();
    }
    return () => {
      console.log("unmounted basic profile");
      mounted = false;
    };
  }, []);

CorporateManagerDetailSection

  React.useEffect(() => {
    let mounted = true;
    if (mounted) {
      fetchCountryList();
      fetchAreaList();
      fetchLocationList();
    }
    return () => {
      mounted = false;
    };
  }, []);

这是公司资料页面,当 axios 调用正确完成时,我将这些部分称为可见

CorporateProfilePage.js

 {isUpdated ? (
        <div className={classNames(classes.main, classes.mainRaised)}>
          <div className={classes.container}>
            {isLoading ? (
              <LoadingModal />
            ) : (
 ////////SKIPPING ////////
<GridContainer>
                  <GridItem xs={12} sm={12} md={8}>
                    <Card>
                      <CardBody>
                        <h3 className={classes.cardTitle}>About</h3>
                        <h5 className={classes.cardDetail}>
                          {profileRecord.companyProfile}
                        </h5>
                      </CardBody>
                    </Card>
                    <CorporateBasicProfileSection />
                  </GridItem>
                  <GridItem xs={12} sm={12} md={4}>
                    <CorporateTagSection />
                    <CorporateManagerDetailSection />
                    <CorporateJobLinkSection />
                  </GridItem>
                </GridContainer>


我不确定这段代码有什么问题,这不是模态组件,所以我不确定为什么会出现上述问题,请给我一些指导。早点感谢。

axios获取主表数据的抓取代码

export const getCountryId = () => {
  const res = axios.get(`${instanceUrl}/api/md/get-all-country`);
  return res;
};
export const getAreaCodeId = () => {
  const res = axios.get(`${instanceUrl}/api/md/get-all-area-code`);
  return res;
};
export const getLocationId = () => {
  const res = axios.get(`${instanceUrl}/api/md/get-all-location`);
  return res;
};
export const getEducationLevelId = () => {
  const res = axios.get(`${instanceUrl}/api/md/get-all-education-level`);
  return res;
};
export const getIndustryId = () => {
  const res = axios.get(`${instanceUrl}/api/md/get-all-industry`);
  return res;
};
export const getLocationById = (countryId) => {};
export const getSchoolId = () => {
  const res = axios.get(`${instanceUrl}/api/md/get-all-school`);
  return res;
};

export const getFieldStudyId = () => {
  const res = axios.get(`${instanceUrl}/api/md/get-all-study-field`);
  return res;
};

export const getCurrencyId = () => {
  const res = axios.get(`${instanceUrl}/api/md/get-all-currency`);
  return res;
};
export const getCompanyTypeId = () => {
  const res = axios.get(`${instanceUrl}/api/md/get-all-company-type`);
  return res;
};

【问题讨论】:

    标签: reactjs use-effect


    【解决方案1】:

    没有看到你的 axios 获取的代码是什么我不能确定,但​​如果你只是在内部进行提取而没有任何取消逻辑,那么这些仍然会在以下情况下进行:

    • 在卸载组件之前触发效果
    • 在卸载组件之前,提取不会完成。

    这里有关于如何取消 axios fetches 的详细信息:https://github.com/axios/axios#cancellation

    您需要在清理回调中编写取消这些提取的逻辑。

    编辑:您基本上需要在效果中创建一个取消令牌(在调用提取之前),然后将该取消令牌传递给所有提取(如上面链接的文档所述,一个取消令牌足以满足许多请求)

    比如:

      React.useEffect(() => {
        const CancelToken = axios.CancelToken;
        const source = CancelToken.source();
        fetchIndustryList(source.token);
        fetchCompanyList(source.token);
        return () => {
          source.cancel('Operation canceled by the user.');
          mounted = false;
        };
      }, []);
    

    并且您需要更改所有函数以接受该取消令牌:

    export const getCountryId = (token) => {
      const res = axios.get(`${instanceUrl}/api/md/get-all-country`, { cancelToken: token });
      return res;
    };
    

    【讨论】:

    • 感谢您的评论,我将在上面添加我的axios获取,
    • @Jin 我已经更新了这方面的答案。这个例子可以理解吗?
    • 路易陈你真是个天才!!!!!!!!!我已经尝试过与您与我分享的类似方法,并且效果很好!!!非常感谢!祝您有美好的一天:)))
    猜你喜欢
    • 2021-08-19
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    • 1970-01-01
    • 2013-11-23
    • 2021-07-01
    相关资源
    最近更新 更多