React hook的那些坑 理解closure闭包

前言

最近开始学习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遇到闭包问题的话,一定要检查依赖是否正确

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值