当前位置: 首页 > news >正文

React hooks的闭包陷阱

react hooks 陷阱

  • hooks必须放在函数顶层, 不能在条件分支和方法内

1、useState陷阱

异步陷阱

function Index() {const [count, setCount] = useState(0)function add(){setCount( count + 1 )console.log(count);  // 0}return (<div><span>{count}</span><button @click=()=>{ add() }> + </button></div>)
}

点击一次按钮,发现页面是更新了,但是console还是上一次的值

【解决方法】:

  • 所以我们不能修改后,把值去拿去其他操作 (应该拿 count+1)
  • 可以通过 promise 来 .then 获取 最新 👇
function Index() {const [count, setCount] = useState(0)function add(){new Promise((resolve) => {setCount((count) => {resolve(count + 1)return count + 1})}).then((res) => {// 下一步操作console.log(res)})}return (<div><span>{count}</span><button onClick={add}> ++ </button></div>)
}

合并陷阱,只执行最后一个

function Index() {const [count, setCount] = useState(0)function add(){setCount( count + 1 )setCount( count + 2 )setCount( count + 3 ) // 只执行这个}return (<div><span>{count}</span><button onClick={add}> ++ </button></div>)
}

此时 只执行了 最后一个 setCount , 导致数据部分逻辑未执行
如果出现这种 判断条件多次 操作 useState 怎么解决 👇

function add(){let num = count;if(...) { num += 1; }if(...) { num += 2; }if(...) { num += 3; }setCount( num );}

那就不写多个setCount

再看个例子:

function Index() {const [count, setCount] = useState(100);function add(){// 合并setCount( count + 1 )setCount( count + 1 )console.log(1, count) // 100// 传入函数,不会合并setCount( count => count + 1 )setCount( count => count + 3 )console.log(2, count) // 100// 点击一次后 count显示为105}return (<div><span>{count}</span> <button onClick={() => add() } > + </button></div>)
}

2、useEffect 陷阱

过期闭包

function Index() {const [count, setCount] = useState(0)useEffect(()=>{setInterval(() => {   console.log(`Count: ${count}`)  }, 1000)}, [])return (<div><span>{count}</span><button onClick=()=>{ setCount(count+1) }> + </button></div>)
}

默认就会运行 每隔1s打印0
点击按钮,count有更新,但是console一直是0
说明此时的 useEffect 中的 count ,还是取的 过期的值

react特点,每次更新都会重新执行这个函数,每次就+1, 是另外一个函数了,不是原来这个函数
但是setInterval的count永远是第一个函数里面的,形成了闭包

【解决方法】:
需要,添加依赖项 count ,
并且每次更新,添加计时器,结束改变计时器

function Index() {const [count, setCount] = useState(0);useEffect(()=>{const time = setInterval(() => {   console.log(`Count: ${count}`)  }, 1000)return () => { clearInterval(time) } // 关键  清除上一次的setInterval }, [count])return (<div><span>{count}</span><button @click=()=>{ setCount(count+1) }> + </button></div>)
}

3、useCallback 陷阱

useCallback 本来拿来优化性能,当依赖变化不用重新注册该函数
使用不当 也会出现一定的问题

获取父组件的值,不是最新

function Parent() {let [count, setCount] = useState(0);return (<div><button onClick={() => setCount(count+1)}> +1 </button>// 子组件<Child count={count} /></div>)
}function Child(props){let log = useCallback(() => {  console.log(props.count)  }, [])return (<div>count: {props.count}<button onClick={() => log()}> 打印 </button></div>)
}

此时我们在 父组件点击 增加按钮
子组件的 count 发生改变 ,我们在点击打印按钮,发现count 一直是0
说明useCallback 依赖为【】数组,取到count 已经过期了

【解决方法】
方法1 :等于没有优化 (依赖更新,useCallback重写一次)

  let log = useCallback(() => {  console.log(props.count)  }, [props.count])

方法2 :将获取 count 的方法 创建到父组件,子组件调用父组件方法

function Parent() {let [count, setCount] = useState(0);let log = useCallback(() => {  console.log(count)  }, [])return (<div><button onClick={() => setCount(count+1)}> +1 </button>// 子组件<Child count={count} log={log} /></div>)
}function Child(props){return (<div>count: {props.count}<button onClick={() => props.log()}> 打印 </button></div>)
}
http://www.lryc.cn/news/211520.html

相关文章:

  • 20.3 OpenSSL 对称AES加解密算法
  • 一文详解防御DDoS攻击的几大有效办法
  • Python二级 每周练习题24
  • MySQL - Buffer Pool
  • c++ 拆分函数返回值和参数类型
  • Ubuntu 23.10安装TeXlive并安装CTEX中文支持
  • SpringBoot中CommandLineRunner详解(含源码)
  • 通信基础(一):数据传输基础
  • 故障诊断模型 | Maltab实现BiLSTM双向长短期记忆神经网络故障诊断
  • 物联网和互联网医院小程序:如何实现医疗设备的远程监测和管理?
  • sharepoint2016-2019升级到sharepoint订阅版
  • CTFHub | MySQL流量、Redis流量、MongoDB流量的WriteUp
  • NSS刷题 js前端修改 os.path.join漏洞
  • ArcGIS Maps SDK for JS:隐藏地图边框
  • 带你秒懂MySQL!! 一万字详细知识点和基础操作 欢迎评论区怼我 (三)
  • kubeadmin部署k8s1.27.4
  • 【Aurix Tricore】HighTec启动代码crt0-tc37x.c分析笔记
  • Linux高级命令(扩展)
  • LLM在text2sql上的应用 | 京东云技术团队
  • 【MySQL】 复合查询 | 内外连接
  • 【linux】麒麟v10安装openjdk8
  • 项目部署与上线
  • 系统架构主题之八:非功能性需求对系统架构及设计的影响
  • 盛元广通化工实验室管理系统
  • 代码没注释?一个方法几百行?
  • Angular-04:指令
  • [SpringCloud] Eureka 与 Ribbon 简介
  • 【Python 零基础入门】常用内置函数 再探
  • 10.30二叉树一些性质,找公共祖先(一般与搜索树),操作的复杂度,选择题细节
  • 亮氨酸脯氨酸肽——一种新型的医药中间体研究肽