React中immutable的使用
从现在开始,努力学习吧!本文《React中immutable的使用》主要讲解了Reactimmutable等等相关知识点,我会在golang学习网中持续更新相关的系列文章,欢迎大家关注并积极留言建议。下面就先一起来看一下本篇正文内容吧,希望能帮到你!
react 一直遵循UI = fn(state) 的原则,有时候我们的state却和UI不同步 有时候组件本身在业务上不需要渲染,却又会再一次re-render。之前在项目中遇到的一些问题,这里做一个简单的分析,大家可以一起交流一下
UI组件渲染性能
react每次触发页面的更新可大致分成两步:
- render(): 主要是计算v-dom的diff
- commit阶段 :将得到的diff v-dom一次性更新到真实DOM
一般我们讨论的渲染 指的是第一步, 我可以悄悄的告诉你 第二步我们也管不了,什么时候更新真实DOM, React有一套自己的机制
组件渲染分为首次渲染和重渲染,首次渲染不可避免就不讨论 重渲染指当组件state或者props发生变化的时候造成的后续渲染过程,也是本文的讨论重点
其实React 在更新组件这方面 一直都有一个诟病 就是:
父组件重渲染的时候,会递归重渲染所有的子组件
const List = () => { const [name, setName] = useState(""); // 用来测试的其它状态值 const [count, setCount] = useState (0); const handleInputChange = (e: React.ChangeEvent ) => { const val = e.target.value; setName(val); }; const handleClick = () => { setCount((c) => c + 1); }; return ( ); }; const Child: React.FC = (props) => { console.log("Child has render"); return count:{props.count}
; };
当 Input name改变的时候 List触发rerender Child会发生rerender 可是Child 依赖的props只有count而已, 如果所有的子组件都被迫渲染,计算在render花费的时间和资源有可能成为性能瓶颈.
方案一:shallow compare
React其实刚出来就提供了优化的手段:
- shouldComponentUpdate: 返回false 就直接跳过组件的render过程
- React.PureComponent: 对props进行浅比较,如果相等 则跳过render 用于class 组件
- React.memo: 也是进行浅比较,适用于functional Component
本文设计的组件以functioal component为主 因为后面会涉及到hooks的使用,对上述例子修改:
const Child: React.FC= React.memo((props) => { console.log("Child has render"); return count:{props.count}
; })
很好 child没有跟着name重渲染了,如果props是一个对象呢?
const List = () => { const [name, setName] = useState(""); // 用来测试的其它状态值 const [count, setCount] = useState (0); console.log(count) const handleInputChange = (e: React.ChangeEvent ) => { const val = e.target.value; setName(val); }; const handleClick = () => { setCount((c) => c + 1); }; const item: IItem = { text: name, id: 1, }; return ( ); }; const Child: React.FC = React.memo( ({ item }) => { console.log("Child has render"); return text:{item.text}
; } );
改变name时候Child会改变 这是预期内的 而当改变count时,Child还是会重渲染,这是什么原因呢?因为count改变后 List组件会rerender 从而导致导致 item这个对象又重新生成了 导致child每次接受的是一个新的object对象 由于每个literal object的比较是引用比较 虽然前后属性相同,但比较得出的结果为false,造成 Child rerender 。
浅比较一定要相同引用吗?不一定,一般的面试中浅比较只是对值的比较 但是React.memo中要求引用类型一定要相同 为什么呢?我猜是出于对性能的考虑,不用深比较也是为了节约性能 通常情况下 我们想要的UI对应的是每个叶子节点的值 ,即只要叶子节点的值不发生变化 就不要rerender
方案:
- 直接对前后的对象进行deepCompare
还好React.memo有第二个参数可以使用
const Child: React.FC = React.memo( ({ item }) => { console.log("Child has render"); returntext:{item.text}
; }, (preProps, nextProps) => { return _.isEqual(preProps, nextProps); // lodash的深比较 } );
- 保证引用相等的情况下,值也相等 useRef
const item: MutableRefObject= React.useRef({ text: name, id: 1, });
好家伙,name无论怎么变化 Child 始终不会更新,useRef保证了返回的值是一个MutableObject 不可变的,意思就是引用完全相同 不管值变化 就不会保持更新.导致了UI不一致,那么我们怎么保证 name 不变的时候 item 和上次相等,name 改变的时候才和上次不等。useMemo
const item: IItem = React.useMemo( () => ({ text: name, id: 1, }), [name] // name变化触发item不等 name不变item和上次相同 );
总结:
- 父组件重渲染的时候,会递归重渲染所有的子组件
- 对primitive 值的数据 React比较值的相等来判断是否重渲染组件 对Object数据 React比较引用 如果引用相同 不会重渲染,如果引用不同 会认为是不同对象 造成重渲染
- useRef返回一个MutableRefObject数据 永远返回的是同一个引用 直到生命周期结束,官网的注解
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.
- (
- useMemo 返回一个计算的值 当dep改变时 返回的值才改变(引用的改变)
今天带大家了解了Reactimmutable的相关知识,希望对你有所帮助;关于数据库的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

- 上一篇
- Go 中 time.After 可能导致的内存泄露问题解析

- 下一篇
- 一文带你深入理解Golang中的泛型
-
- 称心的台灯
- 这篇博文真及时,太详细了,写的不错,mark,关注作者了!希望作者能多写数据库相关的文章。
- 2023-05-20 13:21:45
-
- 数据库 · Redis | 14小时前 | redis redis-check-rdb 数据文件损坏 redis-check-aof 恢复步骤
- Redis数据文件损坏后的恢复攻略
- 465浏览 收藏
-
- 数据库 · Redis | 1天前 | redis Django 缓存 settings.py django-redis
- Django项目Redis缓存集成详解步骤
- 458浏览 收藏
-
- 数据库 · Redis | 2天前 |
- Redis启动时如何指定配置文件
- 225浏览 收藏
-
- 数据库 · Redis | 2天前 |
- Redis启动后无法访问?排查与解决攻略
- 498浏览 收藏
-
- 数据库 · Redis | 3天前 |
- Redis启动后访问异常?快速排查与解决
- 206浏览 收藏
-
- 数据库 · Redis | 3天前 |
- 检查Redis版本及升级指南
- 335浏览 收藏
-
- 数据库 · Redis | 4天前 |
- 检查Redis版本及升级指南
- 134浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 笔灵AI生成答辩PPT
- 探索笔灵AI生成答辩PPT的强大功能,快速制作高质量答辩PPT。精准内容提取、多样模板匹配、数据可视化、配套自述稿生成,让您的学术和职场展示更加专业与高效。
- 23次使用
-
- 知网AIGC检测服务系统
- 知网AIGC检测服务系统,专注于检测学术文本中的疑似AI生成内容。依托知网海量高质量文献资源,结合先进的“知识增强AIGC检测技术”,系统能够从语言模式和语义逻辑两方面精准识别AI生成内容,适用于学术研究、教育和企业领域,确保文本的真实性和原创性。
- 35次使用
-
- AIGC检测-Aibiye
- AIbiye官网推出的AIGC检测服务,专注于检测ChatGPT、Gemini、Claude等AIGC工具生成的文本,帮助用户确保论文的原创性和学术规范。支持txt和doc(x)格式,检测范围为论文正文,提供高准确性和便捷的用户体验。
- 37次使用
-
- 易笔AI论文
- 易笔AI论文平台提供自动写作、格式校对、查重检测等功能,支持多种学术领域的论文生成。价格优惠,界面友好,操作简便,适用于学术研究者、学生及论文辅导机构。
- 46次使用
-
- 笔启AI论文写作平台
- 笔启AI论文写作平台提供多类型论文生成服务,支持多语言写作,满足学术研究者、学生和职场人士的需求。平台采用AI 4.0版本,确保论文质量和原创性,并提供查重保障和隐私保护。
- 40次使用
-
- redis复制有可能碰到的问题汇总
- 2023-01-01 501浏览
-
- 使用lua+redis解决发多张券的并发问题
- 2023-01-27 501浏览
-
- Redis应用实例分享:社交媒体平台设计
- 2023-06-21 501浏览
-
- 使用Python和Redis构建日志分析系统:如何实时监控系统运行状况
- 2023-08-08 501浏览
-
- 如何利用Redis和Python实现消息队列功能
- 2023-08-16 501浏览