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

React性能优化

三个可以优化的地方

避免过度多次渲染 

组件会在以下情况下重新渲染

注意:例如组件组合的形式,<Test><Counter></Counter></Test>,即使Test发生了重新渲染,Counter也不会重新渲染。另外使用React这样的库或框架时,渲染指的是组件函数被调用的过程。这个过程并不一定意味着文档对象模型(DOM)实际上被更新了。它只是意味着组件的逻辑被执行,可能会重新计算组件的状态和属性。

 什么是过度渲染呢?

  • 无效渲染是指组件函数被调用了,但是并没有导致DOM的任何变化。
  • 这通常发生在组件的状态或属性没有改变,但组件仍然被重新渲染的情况下。这种渲染是不必要的,因为它消耗了资源但没有带来任何视觉上的变化。
  • 当然这在react中大部分情况下是没问题的,只有这种情况过度频繁时才会产生问题。

记忆化

组件、对象、函数都可以记忆化。

 memo
工作原理
  1. 创建不会重新渲染的组件

    • memo用于创建一个组件,当其父组件重新渲染时,如果传入的props在两次渲染之间没有变化,那么这个被memo包裹的组件将不会重新渲染。
  2. 只影响props

    • memo只对组件的props进行比较。如果一个被memo包裹的组件在props没有变化的情况下,即使它自己的state发生了变化,或者它订阅的context发生了变化,它仍然会重新渲染。

局限性

  1. 在React中,每次渲染都会重新创建所有内容(包括对象和函数): 这意味着,即使组件的状态没有改变,每次渲染时,组件内部的函数和对象都会被重新实例化。

  2. 在JavaScript中,两个看起来相同的对象或函数实际上是不同的({} != {}): 在JavaScript中,对象和函数是引用类型。即使两个对象的内容完全相同,它们在内存中的地址也是不同的。这意味着,即使两个对象看起来一样,它们也是两个不同的实例。

  3. 因此,如果将对象或函数作为props传递,子组件在每次重新渲染时都会将它们视为新的props: 当父组件将对象或函数作为props传递给子组件时,由于每次渲染都会创建新的实例,子组件会认为这些props是新的,即使它们的值没有变化。

  4. 如果props在重新渲染之间不同,memo将不起作用memo是React的一个优化技巧,它通过比较props来决定是否重新渲染组件。如果props在两次渲染之间没有变化,memo可以防止不必要的渲染。但是,如果props是对象或函数,即使它们的值没有变化,由于它们是新创建的实例,memo也会认为props已经改变,从而导致子组件重新渲染。

所以,我们需要对对象和函数进行memoization(记忆化),以使它们在重新渲染之间保持稳定(保持不变)

useMemo与useCallback
工作原理
  1. 用于记忆化(memoize)对象和函数

  2. 缓存机制

    • 当你将对象或函数传递给 useMemo 或 useCallback 时,这些值或函数会被存储在内存中(即被“缓存”)。在随后的重新渲染中,只要依赖项(即“输入”)没有变化,就会返回缓存的值或函数。
  3. 依赖数组

    • useMemo 和 useCallback 都接受一个依赖数组,这与 useEffect 的工作方式类似。依赖数组用于追踪哪些值或状态影响到了记忆化的值或函数。
    • 如果依赖数组中的任何一个值发生变化,那么记忆化的值或函数就会被重新创建。这是通过比较新旧依赖项来实现的,只有当依赖项发生变化时,才会触发重新计算。

 使用场景
  1. 防止不必要的渲染

    • 通过与 React.memo 一起使用,可以记忆化 props,以避免不必要的组件重新渲染。
  2. 避免每次渲染时的昂贵重新计算

    • 使用 useMemo 来记忆化那些计算成本较高的值。这样,只有在其依赖项发生变化时,才会重新计算这些值,从而节省性能。
  3. 记忆化在其他 Hook 的依赖数组中使用的值

    • 当某个值被用作另一个 Hook(如 useEffect)的依赖数组中的项时,使用 useMemo 或 useCallback 来记忆化这个值可以避免无限循环的副作用。例如,如果你在 useEffect 的依赖数组中直接使用一个会不断变化的值,可能会导致无限循环的副作用执行。通过记忆化这个值,你可以确保只有当值实际改变时,副作用才会重新运行。
案例

假设我们再App.js中有以下对象和函数,使用了useMemo与useCallback:

  const [isFakeDark, setIsFakeDark] = useState(false);const [posts, setPosts] = useState(() =>Array.from({ length: 30 }, () => createRandomPost()));const handleAddPost = useCallback(function handleAddPost(post) {setPosts((posts) => [post, ...posts]);}, []);const archiveOptions = useMemo(() => {return {show: false,title: `Post archive in addition to ${posts.length} main posts`,};}, [posts.length]);<ArchivearchiveOptions={archiveOptions}onAddPost={handleAddPost}setIsFakeDark={setIsFakeDark}/>

注意下useMemo与useCallback使用方式的细微差别。

 Archive使用memo如下所示:

const Archive = memo(function Archive({ archiveOptions, onAddPost }) {// Here we don't need the setter function. We're only using state to store these posts because the callback function passed into useState (which generates the posts) is only called once, on the initial render. So we use this trick as an optimization technique, because if we just used a regular variable, these posts would be re-created on every render. We could also move the posts outside the components, but I wanted to show you this trick 😉const [posts] = useState(() =>// 💥 WARNING: This might make your computer slow! Try a smaller `length` firstArray.from({ length: 30000 }, () => createRandomPost()));const [showArchive, setShowArchive] = useState(archiveOptions.show);return (<aside><h2>{archiveOptions.title}</h2><button onClick={() => setShowArchive((s) => !s)}>{showArchive ? "Hide archive posts" : "Show archive posts"}</button>{showArchive && (<ul>{posts.map((post, i) => (<li key={i}><p><strong>{post.title}:</strong> {post.body}</p><button onClick={() => onAddPost(post)}>Add as new post</button></li>))}</ul>)}</aside>);
});

注意: 对于state的set函数来说,它不需要useCallback函数,它本身随着渲染就不会改变地址。

减小Bundle大小 

Bundle与Bundle分别是什么?

代码分割

代码分割(Code splitting)是一种在现代前端工程中常用的优化技术,它允许将应用程序的代码库分割成多个小块(bundles),这些小块可以独立于主代码库进行加载。这种方法特别适用于大型应用程序,可以显著提高加载速度和性能

 路由级别代码分割

转变为

Suspense是一个用于处理异步组件加载的组件。它允许你定义一个边界,当其子组件在加载过程中遇到异步操作(如数据获取)而暂停时,可以显示一个备用内容(fallback)。然后Suspense与React的lazy函数结合使用,实现组件的懒加载。这种方式允许你在组件首次渲染时自动触发组件的加载,同时在加载过程中显示一个占位符。

因为懒加载的元素,当你切换到Login或者Pricing等页面的时候, 对应的js的代码块才刚刚从服务器下载过来,需要时间到达客户端。这个时候suspense组件就起到了作用!

相关文章:

React性能优化

三个可以优化的地方 避免过度多次渲染 组件会在以下情况下重新渲染 注意&#xff1a;例如组件组合的形式&#xff0c;<Test><Counter></Counter></Test>,即使Test发生了重新渲染&#xff0c;Counter也不会重新渲染。另外使用React这样的库或框架时&a…...

前端开发流程实操:从概念到上线

在前端开发这个充满创意与技术挑战的领域&#xff0c;一个清晰的开发流程是确保项目顺利进行并达到预期效果的关键。 下面就和大家分享一下前端开发的实操流程。 一、项目启动与需求分析 前端开发不是孤立的&#xff0c;它是整个项目的一部分&#xff0c;所以首先要与项目团…...

Metasploit使用

最近在学Metasploit&#xff0c;Metasploit是一个免费的、可下载的渗透测试框架&#xff0c;通过它可以很容易地获取、开发并对计算机软件漏洞实施攻击&#xff0c;是一个集成了渗透测试全流程的渗透工具。 图一 模块&#xff1a;模块组织按照不同的用途分为7种类型的模块 &am…...

Milvus向量数据库05-常见问题整理

Milvus向量数据库05-常见问题整理 1-什么是PipeLine 这张图展示了一个文档处理和搜索系统的架构&#xff0c;主要分为两个部分&#xff1a;Ingestion Pipeline&#xff08;摄取管道&#xff09;和 Search Pipeline&#xff08;搜索管道&#xff09;。下面是对图中各部分的详细…...

Ruby On Rails 笔记3——表的增删改查

1.Migration Migrations是一种便利的方法,能以重现的方式随时间推移改变数据库schema. 使用Ruby Domain Specific Language (DSL),因此你不用手写SQL,进而使你的schema和changes与数据库独立。 可以把每次migration看作是数据库的一个新“版本”。A schema开始时什么都没有…...

CSS3 动画详解,介绍、实现与应用场景详解

CSS3 动画概述 CSS3 动画是通过 CSS3 的新特性来实现元素的动态变化。与传统的 JavaScript 动画不同,CSS3 动画主要通过 CSS 属性的变化来实现动画效果,具有高效、轻量和易于实现的优点。CSS3 动画通常用于网页的动态交互效果、过渡效果、元素移动、缩放、旋转等场景。 一、…...

Winston-MySQL 使用文档

目录 简介 安装 配置 环境变量配置 日志级别和表配置 创建 Logger 实例 文件传输配置 控制台输出配置 完整代码 使用方法 记录信息日志 记录错误日志 记录警告日志 总结 简介 winston-mysql 是一个为 winston3.x 日志库设计的 MySQL 传输插件&#xff0c;允许你…...

java日期工具: 获取两个时间段的时间段值,Java获得两个日期之间的所有年、月份、日。

文章目录 日期字符串格式化获取两个日期之间的所有日期 (字符串格式)获取两个时间段的时间段值,Java获得两个日期之间的所有年、月份、日。生效时间需要大于当前时间结束时间的月份不能大于当前月份日期字符串格式化 /*** 日期字符串格式化** @param time* @param Format_int…...

【Rive】混合动画

1 混合动画简介 【Rive】动画 中介绍了 Rive 中动画的基础概念和一般动画的制作流程&#xff0c;本文将介绍混合动画的基础概念和一般制作流程。Unity 中混合动画介绍详见→ 【Unity3D】动画混合。 混合动画是指同一时刻多个动画按照一定比例同时执行&#xff0c;这些动画控制的…...

qt应用程序崩溃日志和转储dmp文件对于定位问题

qt应用程序崩溃日志和转储文件对于定位问题 一. DMP 文件包含的信息&#xff1a;二. 分析 DMP 文件的主要方法&#xff1a;三. 生成更详细的 DMP 文件&#xff1a;四. 分析 DMP 文件的注意事项&#xff1a;五. 实用建议&#xff1a;六. 实战 一. DMP 文件包含的信息&#xff1a…...

Mysql架构

连接层 最上层是一些客户端和连接服务&#xff0c;负责客户端的连接&#xff0c;验证账号密码等授权认证 服务层 主要完成大多数的核心服务功能&#xff0c;对sql进行解析&#xff0c;优化&#xff0c;调用函数&#xff0c;如果是查询操作&#xff0c;有没有缓存等操作操作。所…...

杂发单的单据类型一个参数的逻辑

【核准中可改】被产线滥用了。它们可以这样做&#xff0c;开立一张杂发单&#xff0c;打印出来交领导层签名。单据要交财务做核算的。然后去修改杂发单的材料。以为可以瞒天过海。2个仓库&#xff0c;一个中掉坑里&#xff0c;一个发现了它们的拙劣的手段&#xff0c;上报之后没…...

Linux系统 vim 编辑文件搜索关键字用法

1、首先确保在normal模式下&#xff0c;按ESC后不在insert模式 输入 /test或?test 此时就会匹配 test 字符串&#xff0c;并且高亮显示 2、向前搜索 /字符串&#xff1a;按n匹配下一个目标&#xff0c;按N匹配上一个目标 3、向后搜索 ?字符串&#xff1a;按n匹配上一个目标…...

Vue智慧商城项目

创建项目 vue组件库 — vant-ui&#xff08;常用于移动端&#xff09; Vant 2 - 轻量、可靠的移动端组件库 安装vant npm i vantlatest-v2 -S 引入组件 按需导入和全部导入 全部导入 整个组件库的所有组件都导进来&#xff0c;缺点是增加了代码包体积 main.js import…...

Qt Window应用程序去掉控制台窗口

Qt Window应用程序去掉控制台窗口 方式一 set(PROJECT_SOURCESWIN32main.cppmainwindow.hpp )add_executable(Tool-V2${PROJECT_SOURCES} )方式二 set_target_properties(Tool-V2 PROPERTIESMACOSX_BUNDLE TRUEWIN32_EXECUTABLE TRUE )参考文献&#xff1a; cmake Qt 项目…...

软件测试最新项目合集【商城、外卖、银行、金融等等.......】

项目一&#xff1a;ShopNC商城 项目概况&#xff1a; ShopNC商城是一个电子商务B2C电商平台系统&#xff0c;功能强大&#xff0c;安全便捷。适合企业及个人快速构建个性化网上商城。 包含PCIOS客户端Adroid客户端微商城&#xff0c;系统PC后台是基于ThinkPHP MVC构架开发的跨…...

SAP SD学习笔记18 - 投诉处理4 - 请求书订正依赖,投诉处理流程的总结

上一章讲了 Credit/Debit Memo依赖&#xff0c;Credit/Debit Memo。Credit Memo依赖 本质上是一张受注票&#xff1b;Credit Memo 本质上是一张请求票。 SAP SD学习笔记17 - 投诉处理3 - Credit/Debit Memo依赖&#xff0c;Credit/Debit Memo-CSDN博客 本章继续讲本图中的内容…...

VBA批量提取PDF内容的程序

VBA批量提取PDF内容的程序 Sub ExtractPDFText()Dim pdfApp As Acrobat.AcroAppDim pdfDoc As Acrobat.CAcroPDDocDim pdfPage As Acrobat.AcroPDPageDim txtData As StringDim i As IntegerDim filePath As StringDim outputFolder As StringDim outputFileName As String 初…...

C++入门终

目录 一、引用 二、内联函数 三、auto关键字 四、指针空值nullptr 一、引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间 类型&引用变量名(对象名)…...

ubuntu下Qt5自动编译配置QtMqtt环境(10)

文章目录 [toc]1、概述2、下载QtMqtt源码3、编译4、验证5、参考6、视频 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt网络编程 &#x1f448; 1、概述 Qt默认是不包含mqtt库的&#xff0c;如果需要使用到mqtt库就只能自己编译配置&#xff1b; 网络所有的…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...