Warning:useEffect函数中取消所有订阅和异步任务

报错:

image-20211122195849735

react-dom.development.js:88 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 ReportMng
    in Unknown (created by Context.Consumer)
复制代码

翻译一下:

无法对已卸载的组件执行React状态更新。这是一个no-op,但它表明应用程序中存在内存泄漏。若要修复,请在useEffect清理函数中取消所有订阅和异步任务。
复制代码

看下源码中报错的位置:

image-20211122200022573

image-20211122194144874

原因:

组件卸载了,但是仍处于渲染数据状态(如:setState,useState),一般写定时器时候会有出现。其他情况也会,只要组件卸载但仍在更新数据时机

解决如下:

这个错误不大会影响实际使用,解决非常简单。

先讲下hook函数组件的解决:

第一种定时器情况:

const [update, setUpdate] = useState(1);
 useEffect(() => {
    const creatInt = setInterval(() => {    //假设这里写了定时器来更新update
      setUpdate(c => c + 1);
    }, 2000);
return () => {
      clearInterval(creatInt);   //(重点)这里清除掉定时器  
    };
  }, []);
复制代码

第二种useSate情况:

  useEffect(() => {
    let isUnmount = false;      //这里插入isUnmount
    const fetchDetail = async () => {
      const res = await getDetail(detailId);
      if (res.code === 0 && !isUnmount) {  //加上判断isUnmount才去更新数据渲染组件
        setDetail(res.data);
      }
    };
    fetchDetail();
    return () => isUnmount = true;   //最好return一个isUnmount
  }, [detail]);
复制代码

改成这个后warning消失

image-20211122200022573

// const mountedRef = useRef(true); // useEffect清理函数中取消所有订阅和异步任务
  let isUnmount = false; //这里插入isUnmount
  useEffect(() => {
    // if (!permission?.writeAuth) {
    //   window.location.href = `/admin/forbidden?url=${encodeURI(window.location.href)}`;
    // }
    getCityList();

    return () => isUnmount = true; //最好return一个isUnmount
    // mountedRef.current = false;
  }, []);
  // 获取城市列表
  const getCityList = useCallback(async (params: GetAuthCityListResponse) => {
    const res = await getAuthCityList(params);
    if (res?.code === 0 && !isUnmount) {
      // if (!mountedRef.current) return null;
      setCityIdOptions(res?.data);
      console.log('11111', !isNotCreate);
      if (!isNotCreate) {
        getAppealDetails();
      }
    }
  }, []);
  // 查询详情
  const getAppealDetails = useCallback(async () => {}, []);
复制代码

说明:

useEffect相当于class组件的3个生命周期,其中return ()=>{ } 相当于 componentWillUnMount

扫描二维码关注公众号,回复: 13313504 查看本文章

class类组件:原理同hook在 componentWillUnMount 中设置一个 值true 、false来判断是否渲染组件

stackoverflow.com/questions/5…

感谢阅读

❤️关注+点赞+收藏+评论+转发❤️**,原创不易,鼓励笔者创作更好的文章

关注公众号小圆脸儿,一个专注于web前端基础、工程化、面试的前端公众号

猜你喜欢

转载自juejin.im/post/7033788514202288135
今日推荐