如何提高React组件的渲染效率的?在React中如何避免不必要的render?

2023-12-19

面试官:说说你是如何提高组件的渲染效率的?在React中如何避免不必要的render?

一、是什么

react 基于虚拟 DOM 和高效 Diff 算法的完美配合,实现了对 DOM 最小粒度的更新,大多数情况下, React DOM 的渲染效率足以我们的业务日常

复杂业务场景下,性能问题依然会困扰我们。此时需要采取一些措施来提升运行性能,避免不必要的渲染则是业务中常见的优化手段之一

二、如何做

在之前文章中,我们了解到 render 的触发时机,简单来讲就是类组件通过调用 setState 方法, 就会导致 render ,父组件一旦发生 render 渲染,子组件一定也会执行 render 渲染

从上面可以看到,父组件渲染导致子组件渲染,子组件并没有发生任何改变,这时候就可以从避免无谓的渲染,具体实现的方式有如下:

  • shouldComponentUpdate
  • PureComponent
  • React.memo

shouldComponentUpdate

通过 shouldComponentUpdate 生命周期函数来比对 state props ,确定是否要重新渲染

默认情况下返回 true 表示重新渲染,如果不希望组件重新渲染,返回 false 即可

PureComponent

shouldComponentUpdate 原理基本一致,通过对 props state 的浅比较结果来实现 shouldComponentUpdate ,源码大致如下:

if (this._compositeType === CompositeTypes.PureClass) {
    shouldUpdate = !shallowEqual(prevProps, nextProps) || ! shallowEqual(inst.state, nextState);
}

shallowEqual 对应方法大致如下:

const hasOwnProperty = Object.prototype.hasOwnProperty;

/**
 * is 方法来判断两个值是否是相等的值,为何这么写可以移步 MDN 的文档
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/is
 */
function is(x: mixed, y: mixed): boolean {
  if (x === y) {
    return x !== 0 || y !== 0 || 1 / x === 1 / y;
  } else {
    return x !== x && y !== y;
  }
}

function shallowEqual(objA: mixed, objB: mixed): boolean {
  // 首先对基本类型进行比较
  if (is(objA, objB)) {
    return true;
  }

  if (typeof objA !== 'object' || objA === null ||
      typeof objB !== 'object' || objB === null) {
    return false;
  }

  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);

  // 长度不相等直接返回false
  if (keysA.length !== keysB.length) {
    return false;
  }

  // key相等的情况下,再去循环比较
  for (let i = 0; i < keysA.length; i++) {
    if (
      !hasOwnProperty.call(objB, keysA[i]) ||
      !is(objA[keysA[i]], objB[keysA[i]])
    ) {
      return false;
    }
  }

  return true;
}

当对象包含复杂的数据结构时,对象深层的数据已改变却没有触发 render

注意:在 react 中,是不建议使用深层次结构的数据

React.memo

React.memo 用来缓存组件的渲染,避免不必要的更新,其实也是一个高阶组件,与 PureComponent 十分类似。但不同的是, React.memo 只能用于函数组件

import { memo } from 'react';

function Button(props) {
  // Component code
}

export default memo(Button);

如果需要深层次比较,这时候可以给 memo 第二个参数传递比较函数

function arePropsEqual(prevProps, nextProps) {
  // your code
  return prevProps === nextProps;
}

export default memo(Button, arePropsEqual);

三、总结

在实际开发过程中,前端性能问题是一个必须考虑的问题,随着业务的复杂,遇到性能问题的概率也在增高

除此之外,建议将页面进行更小的颗粒化,如果一个过大,当状态发生修改的时候,就会导致整个大组件的渲染,而对组件进行拆分后,粒度变小了,也能够减少子组件不必要的渲染

参考文献

  • https://juejin.cn/post/6844903781679759367#heading-12
  • https://whyta.cn/post/caa00364c45d/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何提高React组件的渲染效率的?在React中如何避免不必要的render? 的相关文章

  • 重用 Jest 单元测试

    我正在尝试使用 Jest 测试几个数据库实现 为了帮助测试这些实现 我首先针对两个实现都预期实现的 API 提出了一组单元测试 我目前正在努力将这两个实现传递给测试套件 下面是最简单形式的 虚拟 MongoDB 实现 class Mongo
  • javascript单线程时onreadystatechange的调用者是谁?

    好吧 我是 javascript 的新手 听说它是单线程的 在我看来 如果您发出异步请求 它应该启动一个自己的线程来控制服务器是否已经响应 这在 JavaScript 中不起作用 我在想是否有一些内置机制可以保存所有侦听器并调用它们 具体取
  • 在 JavaScript 中使用科学计数法的陷阱

    这个问题是not寻求开发人员代码格式化意见 就我个人而言 我更喜欢在 JS 代码中使用科学计数法 因为我相信它更具可读性 为我 6e8比600000000 话虽这么说 我只是在寻找在 JS 中以科学记数法指定数字的潜在风险和缺点 我在野外并
  • JavaScript 日期对象 英国日期

    我有以下代码 datePicker change function dateSet datePicker val dateMinimum dateChange dateSetD new Date dateSet dateMinimumD n
  • jquery是如何实现$(document).ready()的?

    jquery是如何实现的 document ready 当然我可以阅读代码 但我正在寻找这个概念 概念 jQuery ready http api jquery com ready 虽然 JavaScript 提供了在渲染页面时执行代码的
  • 为什么 Chart.js 画布不考虑容器元素的填充?

    我将 Chart js 与简单的折线图一起使用 但 Chart js 计算的宽度和高度属性似乎基于父元素的总宽度和高度 忽略填充 var options maintainAspectRatio false responsive true v
  • IE 下的 Http 请求速度变慢

    在我的 javascript 应用程序中工作时 我注意到使用 IE 11 时 相同的 ajax 请求时间最多延长 10 倍 响应大小完全相同 12 6KB 我看到的唯一区别是 IE 添加 Pragma no cache 不是铬 Chrome
  • 在 React 中使用“ref”作为数组

    当我尝试使用 Redux 在 React 中将输入引用为数组时 我遇到了一些问题 下面的代码将数组中的每一篇文章映射一个面板 var articles this props item array articles map article i
  • ReactJS React-pdf 错误“无法加载 PDF 文件。”经过一些尝试

    我创建了一个 React js 应用程序create react app我正在尝试react pdf查看 pdf 我遇到的问题是我的代码有时有效 有时无效 当我第一次加载应用程序时 pdf 总是加载得很好 但如果我访问网站上的其他链接 ur
  • 使用异步函数等待 onclick 的用户输入

    我是异步新手 也许只是不了解基础知识 但我试图通过调用弹出模式并等待用户提交数据的异步函数来等待来自 onclick 的用户输入 在找到一两个甚至提到使用异步等待页面事件的来源后 这对我的特定任务并不是特别有帮助 我想出了这个 asnyc
  • 如何从对象文字数组中切片数组?

    我有这个数组 其中每个索引都包含一个对象文字 所有对象字面量都具有相同的属性 某些对象文字对于给定属性具有相同的值 我想创建一个包含only那些对象文字 我的想法是对数组进行排序 并将其切片成一个新数组 这是数组 var arr arr 0
  • NEXT JS - 应用程序通过重写呈现两次

    我正在开发一个 NEXT JS 项目 但找不到两次渲染应用程序的解决方案 Problem 添加后rewrites to next config js App被渲染两次 如果移除 则渲染一次 next config js async rewr
  • Ripple 模拟器不会触发事件

    我安装了最新的 Ripple 模拟器 Chrome 商店中提供的最新版本 除了事件之外 一切正常 他们都没有火灾 不仅deviceready就像其他一些堆栈溢出问题一样 没有 既不手动 使用Events窗格 也不会自动 deviceread
  • 单击时显示数组中的下一个图像

    我正在努力设置可以通过屏幕箭头点击的图像 目前 我的图像全部通过循环和数组显示 我已经能够进行设置 以便当您将鼠标悬停在小图像预览上时 主图像将更改为该图像 也就是说 您可以将鼠标悬停在它们上以查看更大的版本 我的数组位于 mongo 模型
  • 通过边框拖放调整 div 大小,无需添加额外的标记

    我有一个绝对定位的侧面板 我需要通过拖动此边框来更改其宽度 我还需要更改边框悬停上的光标 是否可以在不添加另一个 div 进行拖动的情况下做到这一点 这是标记 right panel position absolute border lef
  • Soundcloud CORS

    正如我在文档中读到的那样 Soundcloud api 应该支持 cors http developers soundcloud com docs api guide crossdomain http developers soundclo
  • 如何在Nightwatch中测试伪元素的css属性

    我想使用 Nightwatch 测试我的网站上的背景图像是否正确 但它设置为 before 伪元素的背景 这是 CSS icon circle delete before content background url images svg
  • 如何导出从 HTML DOM 解析器检索到的所有图像?

    我想要 使用从我的网站获取所有图像PHP 简单 HTML DOM 解析器 http simplehtmldom sourceforge net 并将它们全部导出到我的桌面ALL立刻 Not右键单击保存或屏幕截图 OPTIONAL 保存所有h
  • jquery:卸载还是卸载之前?

    当用户从当前页面导航时 我想向服务器发布一条消息 我现在正在使用 unload 但结果不可靠 即使在其文档中也是如此 卸载事件的准确处理 各个版本都有所不同 浏览器 例如 某些版本 Firefox 的触发事件当 链接已被跟踪 但当 窗口已关
  • 预期的 catch() 或返回(promise/catch-or-return)

    我是 JavaScript 新手 这是我在 javascript 中第一个在 firebase 上部署函数的函数 得到这个错误 eslint Unexpected function expression prefer arrow callb

随机推荐

  • ISO认证的意义以及费用

    ISO认证是国际标准化组织制定的一套标准体系 它对于企业来说具有重要的意义 ISO认证可以帮助企业提高管理水平 提升产品品质 增强市场竞争力 同时也是企业拓展市场 开拓客户的重要手段 一 ISO认证的意义 ISO认证具有以下几个方面的意义
  • ExperimentalWarning: The http2 module is an experimental API.

    错误提示 Node js ExperimentalWarning The fs promises API is experimental 原因是node的版本不是最新的 而在项目引入的模块是最新的 node js的版本低于模块的版本 解决方
  • 一键证件照换底色软件哪个好?这款让你的证件照独具特色!

    在我们生活中 有很多时候需要用到证件照 无论是报名考试还是申请签证 都需要提供一张规格标准的证件照片 然而 有时候我们拍摄的照片可能存在一些问题 比如背景色不符合要求 这时候 如果有一款一键证件照换底色软件 就能够轻松解决这个问题了 首先
  • 基于单片机设计的电子指南针(LSM303DLH模块(三轴磁场 + 三轴加速度)

    一 前言 本项目是基于单片机设计的电子指南针 主要利用STC89C52作为主控芯片和LSM303DLH模块作为指南针模块 通过LCD1602液晶显示屏来展示检测到的指南针信息 在日常生活中 指南针是一种非常实用的工具 可以帮助我们确定方向
  • C# Tcplistener,Tcp服务端简易封装

    文章目录 前言 相关文章 前言 设计 代码 简单使用 运行结果 前言 我最近有个需求要写Tcp服务端 我发现Tcp服务端的回调函数比较麻烦 简化Tcp的服务 我打算自己封装一个简单的Tcp服务端 相关文章 C TCP应用编程三 异步TCP应
  • 超级好用的SQL语句大全

    文章目录 一 DDL Data Definition Language 数据定义语言 1 操作库 2 操作表 二 DML Data Manipulation Language 数据操作语言 1 增加 insert into 2 删除 del
  • 如何利用 Kubernetes 的新 CronJob API 进行高效的任务调度

    Kubernetes 的 CronJob API 是在云原生环境中自动执行常规任务的关键功能 本指南不仅引导您完成使用此 API 的步骤 还说明了它非常有用的实际用例 先决条件 正在运行的 Kubernetes 集群 版本 1 21 或更高
  • MySQL数据库:为什么它是您的最佳选择?

    MySQL是一个关系型数据库管理系统 由瑞典MySQL AB公司开发 目前属于Oracle旗下产品 MySQL是最流行的关系型数据库管理系统之一 在WEB应用方面 MySQL是最好的RDBMS Relational Database Man
  • Linux中使用HTTP协议进行API交互的示例——你的“API小伙伴”

    大家好 今天我们要聊聊在Linux中如何使用HTTP协议进行API交互 听起来有点高大上 但其实并不难 让我们一起来看看 首先 我们需要了解什么是API API 全名为应用程序接口 Application Programming Inter
  • Android开发,使用kotlin学习多媒体功能(详细)

    一 通知 1 用到的类和方法 1 Context类 getSystemService 接收一个字符串参数用于确定获取系统的哪个服务 这里我们传入Context NOTIFICATION SERVICE 获取NotificationManag
  • 由于人工智能和自动化,2030 年将不存在的 6 个科技工作岗位

    我们都知道人工智能和自动化已经存在 并且有很多关于它们将如何扰乱日常业务实践以及支撑它们的专业角色的讨论 虽然预测某些工作岗位将彻底消失似乎很戏剧性 但对未来可能发生的情况保持现实态度是明智的 以便为接下来发生的事情做好准备 因此 考虑到这
  • VScode配置mingw C语言环境变量

    C语言IDE VScode VScode是个人比较喜欢的一款IDE软件 鄙人曾同时在VScode软件中运行三个终端 开发Python Golang和C语言 下载地址如下 code visualstudio com VScode配置mingw
  • 独孤思维:年底新项目,8年陪伴共同成长

    没赚到钱的人 为了证明自己的能力和与众不同 他们都会通过不断消费来包装自己 满足自己 感觉好像自己很有钱很牛b 其实都不是自己的钱 也都没有能力去赚钱 本质上 就是满足自己的虚荣心 企图让别人觉得 自己很牛 但是 你让他干个稍微有点技术含量
  • 【Android】百度地图 获取开发密钥,创建应用(保姆级教程)

    进入百度网址 网址 百度地图开放平台 百度地图API SDK 地图开发 baidu com 登录百度账号 进入官网控制台 点击 应用管理 gt 我的应用 gt 创建应用 在创建应用里 应用类型选择Android SDK 接下来 我们要获取发
  • 从零开始学python必看,最强“Python编程三剑客(pdf)”,你值得拥有!

    从0开始学Python 就问你一句 慌不慌 说句实在的 慌 可能是因为你自己没有完整的规划 其实就是不知道从何下手 七七八八乱学一通自然还是觉得无厘头 但今天 我要跟你讲 莫慌 恰好前几天从朋友那得到一套最强 Python编程三剑客 Pyt
  • react创建路由两种方式

    react创建路由两种方式 两种方式都需要下载相关依赖 依赖如下 npm i react router dom 方式一 使用 useRoutes 使用 BrowserRouter 或者 HashRouter 在 index tsx 中 im
  • LeetCode21. Merge Two Sorted Lists

    文章目录 一 题目 二 题解 一 题目 You are given the heads of two sorted linked lists list1 and list2 Merge the two lists into one sort
  • React Jsx转换成真实DOM过程?

    面试官 说说React Jsx转换成真实DOM过程 一 是什么 react 通过将组件编写的 JSX 映射到屏幕 以及组件中的状态发生了变化之后 React 会将这些 变化 更新到屏幕上 在前面文章了解中 JSX 通过 babel 最终转化
  • Linux中使用HTTP协议进行远程访问的示例——你的“云端”小伙伴

    大家好 今天我们要聊聊的是如何在Linux中使用HTTP协议进行远程访问 是的 你没有听错 就是那个我们每天用来浏览网页的HTTP协议 首先 我们需要明白HTTP是什么 HTTP 全名为超文本传输协议 Hypertext Transfer
  • 如何提高React组件的渲染效率的?在React中如何避免不必要的render?

    面试官 说说你是如何提高组件的渲染效率的 在React中如何避免不必要的render 一 是什么 react 基于虚拟 DOM 和高效 Diff 算法的完美配合 实现了对 DOM 最小粒度的更新 大多数情况下 React 对 DOM 的渲染