位置: IT常识 - 正文

React避免组件重复渲染(react避免子组件更新)

编辑:rootadmin
##前言 在 React 开发中如果不去管组件的重复渲染问题,项目稍微复杂一点性能将不堪入目,下面将介绍项目中最常见的例子及解决方案(仅 hooks 组件)。 ##预先了解所用知识 React.memo React.useCallback React.useMemo useMemoizedFn(利用 ... 前言

推荐整理分享React避免组件重复渲染(react避免子组件更新),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:react 组件销毁,react 组件销毁,react 组件销毁,react组件必不可少的函数,React避免组件重渲染,react组件重新加载,React避免组件重渲染,react避免子组件更新,内容如对您有帮助,希望把文章链接给更多的朋友!

在 React 开发中如果不去管组件的重复渲染问题,项目稍微复杂一点性能将不堪入目,下面将介绍项目中最常见的例子及解决方案(仅 hooks 组件)。

预先了解所用知识React.memoReact.useCallbackReact.useMemouseMemoizedFn(利用 ref + useMemo 配合单例模式实现比 useCallback 更加好用的 hook,下面会提,强烈推荐)

没错,只需使用上面4点即可解决大多数组件重复渲染问题,而如何合理去使用呢?

例1: 父组件状态更新导致子组件无效渲染const Parent = () => { const [count, setCount] = useState(0); const [son1Count, setSon1Count] = useState(0); const [son2Count, setSon2Count] = useState(0); return ( <div> {console.log("Parent render")} <button onClick={() => setCount(v => v + 1)}>Parent + 1</button> <button onClick={() => setSon1Count(v => v + 1)}>Son1 + 1</button> <button onClick={() => setSon2Count(v => v + 1)}>Son2 + 1</button> <h3>Parent: {count}</h3> <Son1 son1Count={son1Count} /> <Son2 son2Count={son2Count} /> </div> );};const Son1 = (props) => { return ( <div> {console.log("Son1 render")} Son1: {props.son1Count} </div> );};const Son2 = (props) => { return ( <div> {console.log("Son2 render")} Son2: {props.son2Count} </div> );};

可以看出,无论改变哪个值,所有组件都重新渲染了,理想情况是改变 count 值实际并不需要 Son1 和 Son2 组件重新渲染,改变 son1Count 也不需要 Son2 重新渲染,简而言之就是子组件所依赖的值没发生变化就不需要重新渲染,上面情况只需将子组件用 React.memo 包裹即可:

const Son1 = React.memo((props) => { return ( <div> {console.log("Son1 render")} Son1: {props.son1Count} </div> );});const Son2 = React.memo((props) => { return ( <div> {console.log("Son2 render")} Son2: {props.son2Count} </div> );});React避免组件重复渲染(react避免子组件更新)

可以看到轻松包裹一下就已经达到理想效果,React.memo 本质就是一个高阶组件(HOC),通过浅比较(比较栈内存中的值) props、state 和 render 的内容来判断是否需要重新渲染组件。而有时候子组件不得不依赖父组件的值,但这个依赖的值发生改变又不需要重新渲染组件怎么办,接着看下面例2。

例2: 自定义子组件是否重新渲染const Parent = () => { const [random, setRandom] = useState(Math.random()); const [nowTime, setNowTime] = useState(new Date().toLocaleString()); const timerRef = useRef(); useEffect(() => { timerRef.current = setInterval(() => { setRandom(Math.random()); }, 1000); return () => { clearInterval(timerRef.current); }; }); return ( <div> {console.log("Parent render")} <h3>random: {random}</h3> <button onClick={() => setNowTime(new Date().toLocaleString())}> 点击更新子组件 </button> <Son random={random} nowTime={nowTime} /> </div> );};const Son = React.memo( (props) => { return ( <div> {console.log("Son render")} <p> {props.nowTime}父组件 random 值为: {props.random} </p> </div> ); });

上面例子中,子组件依赖父组件 random 和 nowTime,而子组件理想是在点击按钮 nowTime 发生改变后 才重新渲染组件显示 random 的值,不需要上面那样实时渲染,此时只需要在 React.memo 第二个参数自定义渲染规则即可,React.memo 第二个参数为可选参数:

function memo<P extends object>( Component: FunctionComponent<P>, propsAreEqual?: (prevProps: Readonly<PropsWithChildren<P>>, nextProps: Readonly<PropsWithChildren<P>>) => boolean): NamedExoticComponent<P>;

看函数签名可知,第二个参数可传一个回调函数,回调函数会有两个形参,props 状态改变前的值和改变后的值,返回值为一个布尔值,true 禁止重新渲染,false 将重新渲染,和以往 class 组件中的 shouldComponentUpdate 生命周期钩子用法很像,下面加入自定义渲染判断条件,即只在 props.nowTime 发生改变时进行重新渲染:

const Son = React.memo( (props) => { return ( <div> {console.log("Son render")} <p> {props.nowTime}父组件 random 值为: {props.random} </p> </div> ); }, (prevProps, nextProps) => prevProps.nowTime === nextProps.nowTime);

从上图可见只有 props.nowTime 发生改变才会重新渲染。第二个参数的判断规则在实际开发中还有很多妙用,比如一些情况可以替代 useCallback,后面会提一下。

例3: 向子组件传递方法(状态提升)导致子组件无效渲染const Parent = () => { const [count, setCount] = useState(0); const [sonCount, setSonCount] = useState(0); const allPlus = () => { setCount(v => v + 1); setSonCount(v => v + 1); }; return ( <div> {console.log("Parent render")} <button onClick={() => setCount(v => v + 1)}>Parent + 1</button> <h3>Parent: {count}</h3> <Son allPlus={allPlus} sonCount={sonCount} /> </div> );};const Son = React.memo((props) => { return ( <div> {console.log("Son render")} <p>Son: {props.sonCount}</p> <button onClick={props.allPlus}>All + 1</button> </div> );});

从控制台输出可以看见,当传递一个方法给子组件时,就算使用 React.memo 进行包裹也不济于事,导致该问题出现的根本原因是当 count 发生改变导致父组件发生重新渲染,Parent 组件本质也是一个函数,所以 const allPlus = () => { setCount(count + 1); setSonCount(sonCount + 1); }; 也会重新执行一次,这就意味着 allPlus 已经重新赋值,此时虽然看起来没什么变化,实际上 allPlus 在栈内存中的地址已经改变,而 React.memo 默认正是通过浅比较决定是否重新渲染,也就导致只要父组件发生重绘,子组件一定会跟着无效重绘。使用 React.useCallback 缓存函数解决子组件无效渲染,只需将上面 allPlus 方法使用 useCallback 包裹:

const allPlus = useCallback(() => { setCount(v => v + 1); setSonCount(v => v + 1); }, []);

function useCallback<T extends (...args: any[]) => any>(callback: T, deps: DependencyList): T;

从 useCallback 函数签名看到,需要传递两个参数,第一个传需要缓存的函数,第二个是依赖值,其本质就是返回的是一个 memoized(缓存)函数,在依赖不变的情况下,多次定义的时候,返回的值是相同的,他的实现原理是当使用一组参数初次调用函数时,会缓存参数和计算结果,当再次使用相同的参数调用该函数时,会直接返回相应的缓存结果,上面例子依赖值为空数组,所以无论怎样 allPlus 栈内存值都不会变,也就不会触发子组件无效重绘。在向子组件传递方法时在项目中很多时候会懒得专门

本文链接地址:https://www.jiuchutong.com/zhishi/304635.html 转载请保留说明!

上一篇:织梦DEDECMS栏目后台设置隐藏,前台栏目如何显示(织梦如何给栏目增加缩略图)

下一篇:python中datetime和字符串之间如何转换(python中datetime用法)

  • 高德地图可以微信支付吗(高德地图可以微信零钱支付吗)

    高德地图可以微信支付吗(高德地图可以微信零钱支付吗)

  • 与web站点和web页面密切相关的一个概念是(与wed站点和wed页面)

    与web站点和web页面密切相关的一个概念是(与wed站点和wed页面)

  • 腾讯登录qq闪退(腾讯用qq登录就闪退)

    腾讯登录qq闪退(腾讯用qq登录就闪退)

  • 微星网卡rom是什么(微星网卡驱动是什么名称)

    微星网卡rom是什么(微星网卡驱动是什么名称)

  • 三星w2020什么时候发布(三星w2020什么时候上市)

    三星w2020什么时候发布(三星w2020什么时候上市)

  • xsm支持多少w快充(xsmax最高支持多少w)

    xsm支持多少w快充(xsmax最高支持多少w)

  • 一个差评要多少个好评怎么补回动态(一个差评要多少好评才能低)

    一个差评要多少个好评怎么补回动态(一个差评要多少好评才能低)

  • aux输入是什么意思(aux输入还是输出)

    aux输入是什么意思(aux输入还是输出)

  • 苹果电脑加装固态硬盘(苹果电脑加装固态教程)

    苹果电脑加装固态硬盘(苹果电脑加装固态教程)

  • 钉钉听课时长怎么改(钉钉听课时长怎么才能伪造)

    钉钉听课时长怎么改(钉钉听课时长怎么才能伪造)

  • 支付宝不支持手机号码充值是怎么回事(支付宝不支持手机版本怎么办)

    支付宝不支持手机号码充值是怎么回事(支付宝不支持手机版本怎么办)

  • 保修官换是什么意思(保修期内官换机)

    保修官换是什么意思(保修期内官换机)

  • 苹果xs关机键没反应(iphonexs关机键没反应)

    苹果xs关机键没反应(iphonexs关机键没反应)

  • 华为nova4语音助手在哪(华为nova4语音助手叫什么名字)

    华为nova4语音助手在哪(华为nova4语音助手叫什么名字)

  • word如何使页码连续(word如何使页码从正文开始)

    word如何使页码连续(word如何使页码从正文开始)

  • 演唱会买两张票是连坐吗(演唱会买两张票会只抢到一张吗)

    演唱会买两张票是连坐吗(演唱会买两张票会只抢到一张吗)

  • 金立909如何关掉锁屏(金立调试模式怎么关闭)

    金立909如何关掉锁屏(金立调试模式怎么关闭)

  • 怎么制作小程序(怎么制作小程序游戏)

    怎么制作小程序(怎么制作小程序游戏)

  • 如何画3d立体画(如何画3d立体画教程)

    如何画3d立体画(如何画3d立体画教程)

  • 华为stkal00是什么型号(华为stkal00什么型号手机)

    华为stkal00是什么型号(华为stkal00什么型号手机)

  • 抖音怎么设置自己的id在视频(抖音怎么设置自动关闭屏幕)

    抖音怎么设置自己的id在视频(抖音怎么设置自动关闭屏幕)

  • qq隐身会显示什么状态(qq隐身会显示什么状态图片)

    qq隐身会显示什么状态(qq隐身会显示什么状态图片)

  • 页眉下方的分隔线怎么设置(页眉下方的分隔线设为标准红色2.25磅)

    页眉下方的分隔线怎么设置(页眉下方的分隔线设为标准红色2.25磅)

  • 共享单车定位器在哪里(共享单车定位器长什么样)

    共享单车定位器在哪里(共享单车定位器长什么样)

  • Pytorch复习笔记--导出Onnx模型为动态输入和静态输入(pytorch基础教程)

    Pytorch复习笔记--导出Onnx模型为动态输入和静态输入(pytorch基础教程)

  • 再次回归!Discuz论坛重新恢复运营!(再次回归的成语)

    再次回归!Discuz论坛重新恢复运营!(再次回归的成语)

  • 事业单位交所得税是否可以报国高新
  • 小规模纳税人没有税控盘怎么报税
  • 材料按实际成本计价时发出成本的计算方法有
  • 汇算清缴哪些需要调增调减
  • 抵扣进项税怎么做凭证
  • 税务异常有哪些类型
  • 咨询公司小规模纳税人怎么界定
  • 有限合伙企业要交增值税吗
  • 制造费用在借方表示什么
  • 一般纳税人收入会计分录
  • 结转抵扣
  • 进口增值税和进项税
  • 换货补差价怎么补给商家
  • 没有发票怎么报销入账
  • 跨年度收入计算的增值税如何入账?
  • 三证合一后还要去税务局吗
  • 全额抵扣有哪些
  • 为什么非征期不允许汇总上传
  • 税务局买税控盘需要的资料
  • 正常消耗的直接材料计入当期损益
  • 企业取得的哪些成果
  • 农产品增值税核定扣除管理建议
  • 小企业递延收益计算公式
  • 申报个税是按哪个月的工资表
  • 工程安装人工外包合同怎么写
  • 股东投资追加款怎么做账
  • 出口退税的条件包括哪些( )
  • wcu.exe是什么
  • 计提劳务派遣人数怎么算
  • PHP:pg_consume_input()的用法_PostgreSQL函数
  • 固定资产公允价值变动会计处理
  • 股份支付有哪些基本类型
  • 蚊子叮咬怎么办手抄报
  • 暂估入账的固定资产可以计提折旧吗
  • vscode怎么运行前端
  • php ffi 性能
  • 苏尼亚尼
  • 采购员出差预借差旅费300元
  • 纳什理论是什么
  • 员工社保缴纳规定标准
  • 开具劳务发票需要提供什么资料?
  • 分公司以总公司名义
  • 收到多开发票的会计分录
  • EOFError:EOF when reading a line
  • 融资租赁业务需要什么条件
  • 原始凭证的基本内容有会计分录吗
  • 企业宣传视频制作方案
  • 物业费可税前扣除吗
  • 收据和发票有什么用
  • 销项负数发票是红字发票吗
  • 运输公司车辆保养记录表格
  • 公司银行开户费用怎么报销
  • 不抵扣的进项发票需要在电子税务局操作么
  • 坏账收不回来如何做分录
  • 分期收款销售的会计与纳税处理
  • 单位租赁个人房子怎么缴纳房产税
  • 哪些项目的进项可以抵扣
  • 过路费属于会计哪个科目
  • 土地租金怎么做账
  • 应交增值税明细表公式
  • 2020公司年会奖品清单
  • 单独设置停工损失科目
  • sql server使用教程
  • sql数据库批量添加数据
  • mysql5.7.32免安装教程
  • Windows任务计划高级应用
  • Ubuntu修复安装
  • 最简单最快乐
  • windows8.1的图片
  • 使用jquery操作dom
  • nodejs跳转到指定页面
  • 使用shell命令
  • 批处理文件夹内文件名
  • nodejs微信小程序开发工具
  • javascript怎么样
  • 2000元工资交多少党费
  • 增加税务人员怎么加?
  • 纳税申报表如何看销售额
  • 纳税人谈感受
  • 技术合同备案要求
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设