Vue转React踩坑记录——useEffect组件卸载时使用useState定义的值返回undefined

bug背景:vue转react踩坑。在vue数据是响应式的,卸载时不会出现数据已经赋值但是卸载是undefined情况,除非手动更改为undefined。而在react流行的hooks写法,你要一直操作数据,react提供的useEffect方法的return 里其实就像vue的unMounted生命周期,一些组件卸载时的清理工作都写在retrun里。然而,在卸载的时候要清理的方法一直报undefined。

如何使用useEffect进行组件卸载? 

  1. 依赖变量:如果你想要在组件卸载时执行一些清理工作,那么你应该将需要监听的变量添加到依赖数组中。这样,当这些变量发生变化时,useEffect 会重新执行。

  2. 不需要依赖的卸载逻辑:如果你需要在组件卸载时执行一些清理工作,而这些工作不依赖于组件内部的状态或属性,那么你可以将一个空数组([])作为依赖数组传递给 useEffect。这样,无论组件何时卸载,清理工作都会执行。

以下是一个例子,展示了如何在组件卸载时执行清理工作,而不需要依赖任何变量:

useEffect(() => {
  // 清理函数
  return () => {
    console.log('组件即将卸载,执行清理工作');
  };
}, []); // 空依赖数组,表示副作用只在组件卸载时执行

在这个例子中,即使没有指定任何依赖变量,useEffect 的清理函数也将在组件卸载时执行。

总结来说,是否需要依赖其他变量取决于你的具体需求。如果你需要在组件卸载时执行一些清理工作,并且这些工作依赖于某些变量,那么你应该将这些变量添加到依赖数组中。如果你不需要依赖任何变量,或者清理工作不依赖于组件的状态,那么可以传递一个空数组。

bug复现

 代码类似如下,使用useState定义变量,卸载时不依赖variable,组件意外退出,手动退出,只要卸载了就执行一次。

const CustModal= (props: {...}) => {
  const { source} = props;

  const [variable,setVariable]= useState<string>();
    useEffect(()=>{
      ...
    }
,[source])
  useEffect(() => {
    return ()=>{
        if(variable){//卸载时undefined
            clear();
        }
    }
  }, []);
}

const fun=()=>{
    //视图操作
      setVariable("更改");
}

bug产生原因 

这里在第二个useEffect写的卸载方法。而这个useEffect依赖的是空数组,这个useEffect里的内容只会执行一次,及return 外一次,return 里方法一次。因为我们的变量赋值不是在这个useEffect里写的,所以对于useEffect卸载的时候它拿到的是初始值variable,这里使用useState没有定义默认值,所以是undefined。如果这样写,你一定能明白什么意思

假设卸载前一定会执行setVariable给variable赋值,那么第二个useEffect卸载时拿到的variable是什么呢?

答案是“我是初始值”

为什么?还是useEffect不依赖任何变量的情况下,之后执行一次,可以理解为对于第二个useEffect来说它只知道variable初始化,对于后面发生了什么是不知道的。所以卸载的时候只拿到了定义的变量值

const CustModal= (props: {...}) => {
  const { source} = props;

  const [variable,setVariable]= useState<string>("我是初始值");
    useEffect(()=>{
      ...
    }
,[source])
  useEffect(() => {
    console.log(variable);
    return ()=>{
        if(variable){//卸载时"我是初始值"
            clear();
        }
    }
  }, []);
}
//假设卸载前一定会执行
const fun=()=>{
    //视图操作
      setVariable("更改");
}

bug解决 

后来使用了useRef去定义变量就能拿到卸载时的值了

const CustModal= (props: {...}) => {
  const { source} = props;
   //使用useRef定义变量
  const variable = useRef<string>();

  useEffect(()=>{
     variable.current = source;
  }
,[source])
  useEffect(() => {
    return ()=>{
        if(variable.current){
            clear();
        }
    }
  }, []);
}

为什么使用useRef定义变量不会销毁? 

在修复的代码里,使用 useRef 来管理 variable 的状态。useRef 返回的对象有一个 current 属性,用于存储引用。这个引用值在组件的整个生命周期中保持不变,直到组件被卸载。因此,即使在组件卸载时访问 variable.current,它仍然会保持最后的值,而不是 undefined

总结

如果想模拟vue组件卸载只执行一次的逻辑,useEffect里不依赖任何值;而且又想拿到在组件里被修改的数据,就用useRef去定义变量!!!!

  • 15
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三月的一天

你的鼓励将是我前进的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值