bug背景:vue转react踩坑。在vue数据是响应式的,卸载时不会出现数据已经赋值但是卸载是undefined情况,除非手动更改为undefined。而在react流行的hooks写法,你要一直操作数据,react提供的useEffect方法的return 里其实就像vue的unMounted生命周期,一些组件卸载时的清理工作都写在retrun里。然而,在卸载的时候要清理的方法一直报undefined。
如何使用useEffect进行组件卸载?
-
依赖变量:如果你想要在组件卸载时执行一些清理工作,那么你应该将需要监听的变量添加到依赖数组中。这样,当这些变量发生变化时,
useEffect
会重新执行。 -
不需要依赖的卸载逻辑:如果你需要在组件卸载时执行一些清理工作,而这些工作不依赖于组件内部的状态或属性,那么你可以将一个空数组(
[]
)作为依赖数组传递给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去定义变量!!!!