电脑连上网打不开网页,wordpress seo.php,做网站推广利润,免费创建企业网站前言
React中最让人畅谈的就是其带来的灵活性#xff0c;可以说写起来非常的舒服。但是也就是它的灵活性太强#xff0c;往往让我们忽略了很多细节的地方#xff0c;而就是这些细节的东西能进行优化#xff0c;减小我们的性能开销。可以说刚学React和工作几年后写React的代…前言
React中最让人畅谈的就是其带来的灵活性可以说写起来非常的舒服。但是也就是它的灵活性太强往往让我们忽略了很多细节的地方而就是这些细节的东西能进行优化减小我们的性能开销。可以说刚学React和工作几年后写React的代码真的是完全不一样。 废话不多说了今天带大家来了解useCallback有哪些细节之处可以让我们做进一步的性能优化。 如果你不太了解useCallback可以看看我这篇文章正确使用useCallback的姿势
没做优化前的代码
简单的一个结构父子组件子组件接收父组件触发数字改变的函数。
父组件
import React, { memo, useState } from react;
import Son from ../commponet/Son;const Optimize memo(() {console.log(Optimize 组件重新渲染了);const [count, setcount] useState(10);const [isshow, setisshow] useState(true);// 未优化const addNum () {setcount(count 10);};const changeShow () {setisshow(!isshow);};return (divh2Optimize/h2h3count:{count}---isshow:{isshow.toString()}/h3button onClick{(e) addNum()}add10/buttonbutton onClick{(e) changeShow()}changeshow/buttonSon addNum{addNum} //div);
});export default Optimize;
子组件
import React, { memo } from react;interface Props {count?: number;addNum: Function;
}const Son memo((props: Props) {const { addNum } props;console.log(Son 组件重新渲染了);return (divh2Son/h2button onClick{(e) addNum()}click/button/div);
});export default Son;
测试—结论
三个按钮都点击一遍发现 原因不用多说了吧看过我之前那篇文章的都懂下面进行进一步优化。
第一次优化
使用useCallback来进行优化 父组件只贴一些关键代码 子组件代码未改变这里就不贴了
// 第一次优化const addNum useCallback(() {setcount(count 10);}, [count]);const changeShow useCallback(() {setisshow(!isshow);}, [isshow]);测试—结论
前两次点击都是触发 addNum 最后一次点击触发 changeShow 一般优化都只是到此为止可是我们想想子组件中并未用到我们的count 只是接收了addNum函数如果我们能只让父组件进行更新子组件不更新不才是最理想的状态吗
最终优化
首先要搞明白为什么子组件会更新那是因为每次count更新时重新生成一个新函数引用地址发生了变化子组件发现前后两次地址不一样所以进行了更新。那能不能让其始终用最开始的函数地址呢 const changeShow useCallback(() {setisshow(!isshow);}, [isshow]);// 第二次优化const countRef useRef(count);countRef.current count;const addNum useCallback(() {setcount(countRef.current 10);}, []);使用空数组代表我们一直不会改变函数地址用的是最开始的那个函数 那如何修改值呢这里巧妙用useRef来帮助我们记录每次更新的值 为什么使用useRef? 因为useRef是贯穿整个生命周期的每次render重新执行时useRef都是同一个对象。不信那我们测试测试呗。
import React, { memo, useCallback, useRef, useState } from react;
import Son from ../commponet/Son;let obj: any null;
const Optimize memo(() {const aaa useRef();console.log(obj aaa);obj aaa;console.log(Optimize 组件重新渲染了);const [count, setcount] useState(10);const [isshow, setisshow] useState(true);// 未优化const addNum () {setcount(count 10);};const changeShow () {setisshow(!isshow);};return (divh2Optimize/h2h3count:{count}---isshow:{isshow.toString()}/h3button onClick{(e) addNum()}add10/buttonbutton onClick{(e) changeShow()}changeshow/button/div);
});export default Optimize; 可以看到确实是同一个对象的如果我们采用之前的count 或者自己定义一个新对象就会陷入闭包陷阱了 它们都会保存最开始的值的引用后续render更新的是新地址不会被其引用感兴趣的可以去测试测试这里就不测试了。 // 用普通对象和之前值是否可行闭包陷阱const countRef { current: count };countRef.current count;const addNum useCallback(() {// setcount(countRef.current 10);setcount(count 10);}, []);测试—结论
三个按钮都点击了一次发现都只是父组件更新了 总结
这里并不是说所有的 useCallback 都要进行这样处理其实是没必要的。我们要根据实际情况来分析就比如我们上面这个例子那是建立在子组件没有依赖父组件的count数据所以我们可以选择只渲染父组件就可以若是子组件也用到了count数据则推荐使用第一次优化即可。 一键三连关注不迷路