提高 React 性能的技巧

这篇具有很好参考价值的文章主要介绍了提高 React 性能的技巧。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.解决重复渲染问题

我们大多数人都知道虚拟 DOM 是如何工作的,但最重要的是检测何时触发树比较。当我们可以跟踪它时,我们可以控制组件的重新渲染,并最终防止意外的性能流。令人惊讶的是,它并不难捕捉。首先,将 React Devtool 扩展添加到浏览器。

  • 然后打开浏览器开发者工具(在 Chrome 中是 Option + ⌘ + J(在 macOS 上),或 Shift + CTRL + J(在 Windows/Linux 上)。

  • 选择组件

  • 点击设置图标

  • 并选中“组件渲染时突出显示更新”

提高 React 性能的技巧

就是这样,现在,当我们与 UI 交互时,它会在当前重新渲染的元素上显示绿色边框。知道了这一点,我们就可以分析我们的任何 React 组件并重构它们以避免不必要的重新渲染。

2.通过拆分组件减少重新渲染

如果我们能够减少意外重新渲染元素的数量,它将解决 React 中的大部分性能问题。

但我们必须首先回答这个问题:“是什么触发了重新渲染?”。答案很简单,状态改变了。

每次组件状态发生变化时,它都会唤醒树比较,也称为协调,并重新呈现状态上下文的元素。

状态上下文,是初始化此类状态的组件。意思是,如果我们有一个巨大的组件,它有很多状态(不需要相互依赖)并且其中一个状态发生了变化,它将重新渲染整个组件元素,这绝对不是我们想要的。

那么,解决方案是什么?解决方法是通过将组件的一部分和它的一些状态移动到它自己的子组件中来分离状态上下文,现在,让我们看一下这个例子:

假设我们有一个带有搜索过滤器的表格组件。搜索过滤器是一个受控输入,其状态在输入文本更改后更新。这是它的样子:

提高 React 性能的技巧

当我们开始在搜索输入字段中输入时会发生什么?

提高 React 性能的技巧

是的,它将重新呈现整个表格元素。发生这种情况是因为输入状态上下文与表组件共享相同的上下文。

现在,让我们尝试我们的解决方案,将输入元素及其状态移动到一个单独的组件中,并将其注入到表格组件中。

提高 React 性能的技巧

提高 React 性能的技巧

神奇的事情发生了,表格组件不再重新渲染。我们稍后可以通过从输入发出事件来控制我们希望输入影响表格元素的确切时间来增强功能。

好的做法是拆分组件以分离状态上下文,以避免冗余的重新渲染。

3.什么是实例重创建,如何避免?

我们已经发现状态更改会触发组件重新渲染,但是我们需要考虑另一个重要的副作用。

当状态改变和协调发生时,它将重新初始化整个组件实例并保持新的状态值。这对我们来说意味着,在协调期间,将重新创建所有函数实例,以便能够考虑新的状态值,我们不需要它,在大多数情况下,函数可以只依赖于几个状态,我们不想重新创建不依赖于已更改状态的函数实例。

这是一个提高性能的机会,我们有几个解决方案:useCallback 和 useRef。让我们看个例子:

const {someState, setSomeState} = useState('')
const {otherState, setOtherState} = useState('')
const foo = () => {console.log(someState)}

这是最常见的例子。我们有依赖于状态 someState 的 foo。当 someState 改变时,它将重新创建 foo 的新实例。

这段代码的问题是,即使其他一些状态发生变化,比如 otherState,foo 也会被重新创建,这是我们实际上不想要的。我们可以使用 useCallback 来告诉 React 我们的函数状态依赖是什么,以便更明确地说明何时重新创建实例:

const {someState, setSomeState} = useState('')
const {otherState, setOtherState} = useState('')
const foo = useCallback(() => {console.log(someState)}, [someState])

在此示例中,我们将依赖项数组传递给 useCallback 挂钩。更好的是,foo 将避免其他状态更改。

另一种选择是使用 useRef。useRef——你可以把它想象成和 useState 一样,但不会触发组件重新渲染(UI 不会更新)。useRef 没有依赖列表,所以我们需要传递 someState as foo 属性:

const {someState, setSomeState} = useState('')
const {otherState, setOtherState} = useState('')
const foo = useRef((currentSomeState) => {console.log(currentSomeState)}).current;

在这种情况下,我们根本不会重新创建 foo 实例。

结论:使用 useCallback 和 useRef 来控制函数实例的重新创建。

4.不要偷懒懒加载

React 默认同步渲染组件。这意味着组件将等到其子项被渲染后再渲染自己。没有必要等待,尤其是当一些子组件没有耦合时。它可能会导致页面挂起。

假设我们点击了一些导航链接,假设将我们重定向到另一个页面。导航将等待所有页面组件呈现完成重定向。它会影响用户体验,人们不会等待,只会离开您的网站。

我们需要使页面内容异步呈现,以免损害导航。解决方案是将您的页面组件包装到 React.lazy(() 并告诉 React 完成导航,然后等待页面组件完成渲染:

const PageComponent = React.lazy(() => import('./PageComponent'));

稍后我们可以使用在页面组件尚未准备好时,显示一些加载动画。

<Suspense fallback={<div>Loading...</div>}>
   <PageComponent />
</Suspense>

这并不意味着我们必须在任何地方都使用 Lazy load 组件,当我们在不会对性能造成太大损害的地方使用它时,它可能会导致过度工程。

另一种场景是一些组件可能默认隐藏在 UI 中,所以我们不必等待它们。例如模态窗口、对话框、抽屉和可折叠的侧面板。

延迟加载页面组件和隐藏的 UI 组件。

5.何时使用 React 片段?

它经常发生,当我们在 JSX 中构建一些布局并想要对我们的元素进行分组时,在大多数情况下我们使用

标签。或者,例如,我们有我们想要移动到单独组件中的父子 HTML 标记:

<ul>
    <li>Item 1</li> <--- | Want to move it to child <Li> |
    <li>Item 2</li> <--- |                               |
</ul>

因此,当我们将 <li> 移动到单独的组件中时,例如:

const Li = () => {
    return (
        <div>
            <li>Item 1</li>
            <li>Item 2</li>
        </div>
    )
}

并改变它:

<ul>
    <Li/>
</ul>

渲染后,它看起来像这样:

<ul>
    <div>
        <li>Item 1</li>  
        <li>Item 2</li>    
    </div>
</ul>

这将创建一个我们不需要的额外<div>节点。

这将使我们的 DOM 树更加嵌套,从而减慢协调过程。

相反, 我们可以将我们的<div>子元素包装到 Fragment 中。

最初,Fragment 允许您对 DOM 元素进行分组,插入后只会导致一次重排。

在 React 中,Fragment 也会让你减少不必要的节点。当你想对元素进行分组时,你唯一需要做的就是使用 Fragment 而不是 <div>:

const Li = () => {
    return (
        <> /* or <React.Fragment>, or <Fragment>*/
            <li>Item 1</li>
            <li>Item 2</li>
        </>
    )
}

就是这样,就这么简单。

如果要对元素进行分组以减少节点数,请使用 Fragment。

6.避免在列出的元素中使用索引作为键

大家都知道,如果没有,Eslint 会强制执行在列出的元素中使用键,例如:

<ul>
    <li key="1">Item 1</li>  
    <li key="2">Item 2</li>    
</ul>

React 中的关键是唯一标识符,它帮助 React 指向列表中的正确元素并更新正确的元素。如果我们使用索引作为列表中的键,比如:

<ul>
    {[1, 2].map((val, index) => <li key={index}>Item {val}</li>)}  
</ul>

我们将元素映射到它的索引。但是如果我们有排序,列表中元素的顺序可能会改变,初始键将不再指向正确的元素。

始终使用唯一 id 作为列出元素的键,如果对象没有它,您可以使用外部库显式分配,如 uid。

7.避免Spread Props

这是今天的最后一个修改调整技巧,已经很多了, 你一定见过,甚至自己亲手做过spreading props。就像是:

const Input = ({ onChange, ...props }) => (
    <input {...props} onChange={e => onChange(e.target.value)}/>
);

它不仅迫使您猜测实际输入接收到的属性是什么,而且还会在输入元素中创建一堆您不一定需要的属性。

让它明确,并且不要害怕根据需要传递尽可能多的属性,您总是可以将它们分组到某个对象中:

const Input = ({ onChange, inputProps: {value, type, className} }) => (
    <input className={className} type={type} value={value} onChange={e => onChange(e.target.value)}/>
);

很好,现在更具可读性。

永远不要spread props,分别传递每个属性。

总结

我想,您可能已经知道 Eslint 强制执行的一些调整,但是现在您知道为什么遵循它们很重要了,而且,您可以对代码进行性能分析,这将为您提供改进空间。文章来源地址https://www.toymoban.com/news/detail-487048.html

到了这里,关于提高 React 性能的技巧的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Cache:提高应用性能的策略和技巧

    🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页 ——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍专栏》 🐾 学会IDEA常用操作,工作效率翻倍~💐 🌊 《100天精通Golang(基础

    2024年02月09日
    浏览(48)
  • 探讨Redis缓存问题及解决方案:缓存穿透、缓存击穿、缓存雪崩与缓存预热(如何解决Redis缓存中的常见问题并提高应用性能)

    Redis是一种非常流行的开源缓存系统,用于缓存数据以提高应用程序性能。但是,如果我们不注意一些缓存问题,Redis也可能会导致一些性能问题。在本文中,我们将探讨Redis中的一些常见缓存问题,并提供解决方案。 缓存穿透指的是当一个请求尝试访问一个不存在于缓存中的

    2024年02月03日
    浏览(94)
  • CSS 提高性能的方法,并提供一些实用的技巧和代码示例

    CSS 是前端开发中不可或缺的一部分,它负责网页的样式和布局。随着网站规模和复杂度的增加,CSS 的性能也变得越来越重要。本文将介绍 CSS 提高性能的方法,并提供一些实用的技巧和代码示例。 使用压缩后的 CSS 文件 压缩 CSS 文件可以减小文件大小,加快加载速度。常见的

    2024年02月06日
    浏览(59)
  • Spark性能优化:提高计算速度与资源利用率的实用技巧

    Apache Spark是一个开源的大规模数据处理框架,它可以处理批量数据和流式数据,并提供了一个易用的编程模型。Spark的核心组件是Spark引擎,它负责执行用户的计算任务。在大规模数据处理中,Spark性能优化是非常重要的,因为它可以提高计算速度和资源利用率。 在本文中,我

    2024年02月20日
    浏览(64)
  • 在Vue 3中,对于组件中的插槽(slots)生成进行了优化,以提高渲染性能和组件的更新速度。

    在Vue 3中,对于组件中的插槽(slots)生成进行了优化,以提高渲染性能和组件的更新速度。 在Vue 2中,每当一个插槽被渲染时,都会生成一个函数来创建对应的VNode节点。这意味着即使插槽内容保持不变,每次渲染时仍然会重新生成相同的VNode节点。 而在Vue 3中,通过使用新

    2024年02月12日
    浏览(49)
  • react组件多次渲染问题

    问题背景 在数据没有发生变化的情况下React组件会进行数次重复渲染,绘制出来完全相同的两个图 排查思路 寻找子组件重渲染原因实验 测试一:在子组件的props未发生任何变更的情况下是否会发生重新渲染 测试结论:子组件即使不接收任何props当父组件重新渲染时子组件也

    2024年02月12日
    浏览(86)
  • 【React】- 组件生命周期连续渲染两次问题

    最近在整理生命周期相关的知识内容,然后发现一个奇怪的现象,即组件的生命周期会运行2次!经过确认不是代码问题,于是开始找度娘,终于找到其原因-React中的严格模式,在这里记录一下 一、问题重现 如图所示,当组件初始化渲染时,每个周期都走了2次,按理说初始化

    2024年02月15日
    浏览(37)
  • keep-alive 是 Vue 的一个内置组件,用于缓存其他组件的实例,以避免重复渲染和销毁,它可以在需要频繁切换的组件之间提供性能优化

    目录 keep-alive  使用 keep-alive 的示例代码: 手动清除组件缓存的示例代码: keep-alive 组件有以下几个优点: keep-alive 的原理: 使用 keep-alive 组件,你可以包裹需要缓存的组件,然后这些组件在切换时将会被缓存起来,而不是每次都重新创建。 使用 keep-alive 的示例代码: 我们

    2024年02月08日
    浏览(40)
  • React--》React组件变化每次都会导致重新渲染,如何解决?

    目录 React.memo useCallback useMemo React组件会在两种情况下下发生渲染 第一种 :当组件自身的state发生变化时 第二种 :当组件的父组件重新渲染时 第一种情况下重新渲染无可厚非,state都变化了组件自然应该重新进行渲染,但是第二种情况似乎并不是总怎么必要,有时候仅仅只需

    2023年04月21日
    浏览(69)
  • 解决前端性能瓶颈:高效处理大量数据渲染与复杂交互的策略与优化方法

    ✨✨祝屏幕前的小伙伴们每天都有好运相伴左右,一定要天天开心!✨✨  🎈🎈作者主页: 喔的嘛呀🎈🎈 目录 引言 一、分页加载数据 二、虚拟滚动 三、懒加载 四、数据缓存 五、减少重绘和回流 六、优化图片和资源: 七、合并压缩文件 八、使用Web Workers  在前端开发

    2024年04月27日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包