前言
最近开始学习React,跟着Nolan老师开发Jira,有很多干货,这里分享React hook的一个易错点,也就是React Hook中由于closure闭包中会带来的问题以及解决方法
一、Closure的代码段分析
const testClosure = () => {
let num = 0;
const effect = () => {
num += 1;
const message = `num value in message:${num}`;
return function unmount() {
console.log(message);
};
};
return effect;
};
const add = testClosure();
const unmount = add();
add();
add();
add();
unmount(); // 在这里会打印什么呢?
我们一行一行分析
第一行, 执行testClosure,返回引用了message的unmount函数
const add = testClosure();
第二行,返回的是运行effect()的返回值,也是一个函数,unmount(),此时num为1,赋值给unmount
num += 1;
const message = `num value in message:${num}`;
return function unmount() {
console.log(message);
};
第三行,add()就是执行unmount(),返回函数unmount(),此时num为2,并没有赋值给其他变量
return function unmount() {
console.log(message);
};
第四行,add()就是执行unmount(),返回函数unmount(),此时num为3,并没有赋值给其他变量
return function unmount() {
console.log(message);
};
第五行,add()就是执行unmount(),返回函数unmount(),此时num为4,并没有赋值给其他变量
return function unmount() {
console.log(message);
};
第六行,运行unmount,也就是运行第二行的返回函数,num为1,所以打印num value in message:1
二、Rect hook中的closure
2.1 useEffect中的闭包
对于useEffect来说,它会与函数组件形成闭包,也就是useEffect中num的值是Test中num开始的值,为0
export const Test = () => {
const [num, setNum] = useState(0);
const add = () => setNum(num + 1);
useEffect(() => {
return () => {
console.log("卸载值:", num);
};
}, []);
return (
<div>
<button onClick={add}>add</button>
<p>number: {num}</p>
</div>
);
};
那么解决方法就是在useEffect最后的[]中加上num,告诉React每当num改变的时候都需要重新执行一遍
2.2 useRef
那么既然组件中变量是可变的,那么有没有方法保存一个不变的量呢,这就需要用到useRef
useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.
总结
如果在useEffect遇到闭包问题的话,一定要检查依赖是否正确