”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 如何防止不必要的 React 组件重新渲染

如何防止不必要的 React 组件重新渲染

发布于2024-11-14
浏览:120

How to Prevent Unnecessary React Component Re-Rendering

了解 React Native 如何渲染组件对于构建高效、高性能的应用程序至关重要。当组件的状态或属性发生变化时,React 会自动更新用户界面(UI)以反映这些变化。结果,React 再次调用组件的 render 方法来生成更新的 UI 表示。

在本文中,我们将探讨三个 React Hook 以及它们如何防止 React 中不必要的渲染

  • useMemo
  • useCallback
  • useRef

这些工具使我们能够通过避免不必要的重新渲染、提高性能和有效存储值来优化代码。

在本文结束时,我们将更好地了解如何使用这些方便的 React hooks 使我们的 React 应用程序更快、响应更快。

使用 React 的 useMemo

在React中,useMemo可以防止不必要的重新渲染并优化性能。

让我们探索一下 useMemo 钩子如何防止 React 组件中不必要的重新渲染。

通过记住函数的结果并跟踪其依赖关系,useMemo 确保仅在必要时重新计算该过程。

考虑以下示例:

import { useMemo, useState } from 'react';

    function Page() {
      const [count, setCount] = useState(0);
      const [items] = useState(generateItems(300));

      const selectedItem = useMemo(() => items.find((item) => item.id === count), [
        count,
        items,
      ]);

      function generateItems(count) {
        const items = [];
        for (let i = 0; i 
          

Count: {count}

Selected Item: {selectedItem?.id}

); } export default Page;

上面的代码是一个名为Page的React组件,它使用useMemo来优化selectedItem计算。

解释如下:

  • 组件使用 useState 挂钩维护状态变量计数。
  • 项目状态是使用 useState 钩子和generateItems函数的结果来初始化的。
  • selectedItem是使用useMemo计算的,它会记住items.find操作的结果。它仅在计数或项目发生变化时重新计算。
  • generateItems 函数根据给定的计数生成项目数组。
  • 该组件呈现当前的计数值、selectedItem id以及用于增加计数的按钮。

使用 useMemo 通过记住 items.find 操作的结果来优化性能。它确保仅当依赖项(计数或项目)发生变化时才执行 selectedItem 的计算,从而防止后续渲染时不必要的重新计算。

记忆化应该选择性地用于计算密集型操作,因为它会给渲染过程带来额外的开销。

使用React的useCallback

React 中的 useCallback 钩子允许记忆函数,防止它们在每个组件渲染期间被重新创建。通过利用 useCallback。只要其依赖关系保持不变,部件仅创建一次并在后续渲染中重复使用。

考虑以下示例:

import React, { useState, useCallback, memo } from 'react';

    const allColors = ['red', 'green', 'blue', 'yellow', 'orange'];

    const shuffle = (array) => {
      const shuffledArray = [...array];
      for (let i = shuffledArray.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i   1));
        [shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]];
      }
      return shuffledArray;
    };

    const Filter = memo(({ onChange }) => {
      console.log('Filter rendered!');

      return (
         onChange(e.target.value)}
        />
      );
    });

    function Page() {
      const [colors, setColors] = useState(allColors);
      console.log(colors[0])

      const handleFilter = useCallback((text) => {
        const filteredColors = allColors.filter((color) =>
          color.includes(text.toLowerCase())
        );
        setColors(filteredColors);
      }, [colors]);


      return (
        
    {colors.map((color) => (
  • {color}
  • ))}
); } export default Page;

上面的代码演示了 React 组件中的简单颜色过滤和洗牌功能。让我们一步步看一下:

  • 初始颜色数组定义为 allColors.
  • shuffle 函数接受一个数组并随机打乱其元素。它使用Fisher-Yates算法来实现洗牌。
  • Filter 组件是一个记忆化的功能组件,用于呈现输入元素。它接收 onChange 属性并在输入值发生变化时触发回调函数。
  • Page 组件是呈现颜色过滤和洗牌功能的主要组件。
  • 状态变量颜色使用useState钩子进行初始化,初始值设置为allColors。它代表过滤后的颜色列表。
  • handleFilter 函数是使用 useCallback 挂钩创建的。它采用文本参数并根据提供的文本过滤 allColors 数组。然后使用 useState 挂钩中的 setColors 函数设置过滤后的颜色。依赖数组 [colors] 确保仅在颜色状态发生变化时才重新创建 handleFilter 函数,从而通过防止不必要的重新渲染来优化性能。
  • 页面组件内部有一个用于调整颜色的按钮。单击按钮时,它会使用经过排序的 allColors 数组调用 setColors 函数。
  • Filter 组件是通过将 onChange 属性设置为handleFilter 函数来渲染的。
  • 最后,颜色数组被映射以将颜色项列表渲染为
  • 元素。

useCallback 钩子用于记忆 handleFilter 函数,这意味着该函数仅创建一次,并且如果依赖项(在本例中为颜色状态)保持不变,则在后续渲染中重用。

此优化可防止接收 handleFilter 函数作为 prop 的子组件不必要的重新渲染,例如 Filter 组件。
它确保如果颜色状态没有改变,过滤器组件不会重新渲染,从而提高性能。

使用 React 的 useRef

增强 React 应用程序性能并避免不必要的重新渲染的另一种方法是使用 useRef 钩子。使用 useRef,我们可以存储一个在渲染过程中持续存在的可变值,有效防止不必要的重新渲染。

这种技术允许我们维护对某个值的引用,而不会在该值发生变化时触发组件更新。通过利用引用的可变性,我们可以优化特定场景下的性能。

考虑以下示例:

import React, { useRef, useState } from 'react';

function App() {
  const [name, setName] = useState('');
  const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    
setName(e.target.value)} ref={inputRef} />
); }

上面的示例有一个简单的输入字段和一个按钮。 useRef 钩子创建一个名为 inputRef 的引用。一旦单击按钮,就会调用handleClick 函数,该函数通过访问inputRef ref 对象的当前属性来关注输入元素。因此,它可以防止输入值更改时不必要的组件重新渲染。

为了确保 useRef 的最佳使用,请仅将其保留用于不影响组件渲染的可变值。如果可变值影响组件的渲染,则应将其存储在其状态中。

结论

在本教程中,我们探讨了 React 重新渲染的概念及其对应用程序性能的潜在影响。我们深入研究了有助于减少不必要的重新渲染的优化技术。 React 提供了各种钩子,使我们能够增强应用程序的性能。我们可以利用这些钩子在渲染之间有效地存储值和函数,从而显着提高 React 应用程序性能。

版本声明 本文转载于:https://dev.to/harshsolanki05/how-to-prevent-unnecessary-react-component-re-rendering-3jg6?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • Python中嵌套函数与闭包的区别是什么
    Python中嵌套函数与闭包的区别是什么
    嵌套函数与python 在python中的嵌套函数不被考虑闭合,因为它们不符合以下要求:不访问局部范围scliables to incling scliables在封装范围外执行范围的局部范围。 make_printer(msg): DEF打印机(): 打印(味精) ...
    编程 发布于2025-07-18
  • `console.log`显示修改后对象值异常的原因
    `console.log`显示修改后对象值异常的原因
    foo = [{id:1},{id:2},{id:3},{id:4},{id:id:5},],]; console.log('foo1',foo,foo.length); foo.splice(2,1); console.log('foo2', foo, foo....
    编程 发布于2025-07-18
  • 如何在Chrome中居中选择框文本?
    如何在Chrome中居中选择框文本?
    选择框的文本对齐:局部chrome-inly-ly-ly-lyly solument 您可能希望将文本中心集中在选择框中,以获取优化的原因或提高可访问性。但是,在CSS中的选择元素中手动添加一个文本 - 对属性可能无法正常工作。初始尝试 state)</option> < op...
    编程 发布于2025-07-18
  • Java为何无法创建泛型数组?
    Java为何无法创建泛型数组?
    通用阵列创建错误 arrayList [2]; JAVA报告了“通用数组创建”错误。为什么不允许这样做?答案:Create an Auxiliary Class:public static ArrayList<myObject>[] a = new ArrayList<myO...
    编程 发布于2025-07-18
  • Java中Lambda表达式为何需要“final”或“有效final”变量?
    Java中Lambda表达式为何需要“final”或“有效final”变量?
    Lambda Expressions Require "Final" or "Effectively Final" VariablesThe error message "Variable used in lambda expression shou...
    编程 发布于2025-07-18
  • 切换到MySQLi后CodeIgniter连接MySQL数据库失败原因
    切换到MySQLi后CodeIgniter连接MySQL数据库失败原因
    无法连接到mySQL数据库:故障排除错误消息要调试问题,建议将以下代码添加到文件的末尾.//config/database.php并查看输出: ... ... 回声'... echo '<pre>'; print_r($db['default']); echo '</pr...
    编程 发布于2025-07-18
  • 表单刷新后如何防止重复提交?
    表单刷新后如何防止重复提交?
    在Web开发中预防重复提交 在表格提交后刷新页面时,遇到重复提交的问题是常见的。要解决这个问题,请考虑以下方法: 想象一下具有这样的代码段,看起来像这样的代码段:)){ //数据库操作... 回声“操作完成”; 死(); } ?> ...
    编程 发布于2025-07-18
  • 为什么我会收到MySQL错误#1089:错误的前缀密钥?
    为什么我会收到MySQL错误#1089:错误的前缀密钥?
    mySQL错误#1089:错误的前缀键错误descript [#1089-不正确的前缀键在尝试在表中创建一个prefix键时会出现。前缀键旨在索引字符串列的特定前缀长度长度,可以更快地搜索这些前缀。了解prefix keys `这将在整个Movie_ID列上创建标准主键。主密钥对于唯一识别...
    编程 发布于2025-07-18
  • PHP与C++函数重载处理的区别
    PHP与C++函数重载处理的区别
    作为经验丰富的C开发人员脱离谜题,您可能会遇到功能超载的概念。这个概念虽然在C中普遍,但在PHP中构成了独特的挑战。让我们深入研究PHP功能过载的复杂性,并探索其提供的可能性。在PHP中理解php的方法在PHP中,函数超载的概念(如C等语言)不存在。函数签名仅由其名称定义,而与他们的参数列表无关。...
    编程 发布于2025-07-18
  • 人脸检测失败原因及解决方案:Error -215
    人脸检测失败原因及解决方案:Error -215
    错误处理:解决“ error:((-215)!empty()in Function Multultiscale中的“ openCV 要解决此问题,必须确保提供给HAAR CASCADE XML文件的路径有效。在提供的代码片段中,级联分类器装有硬编码路径,这可能对您的系统不准确。相反,OPENCV提...
    编程 发布于2025-07-18
  • 如何使用Python的请求和假用户代理绕过网站块?
    如何使用Python的请求和假用户代理绕过网站块?
    如何使用Python的请求模拟浏览器行为,以及伪造的用户代理提供了一个用户 - 代理标头一个有效方法是提供有效的用户式header,以提供有效的用户 - 设置,该标题可以通过browser和Acterner Systems the equestersystermery和操作系统。通过模仿像Chro...
    编程 发布于2025-07-18
  • 编译器报错“usr/bin/ld: cannot find -l”解决方法
    编译器报错“usr/bin/ld: cannot find -l”解决方法
    错误:“ usr/bin/ld:找不到-l “ 此错误表明链接器在链接您的可执行文件时无法找到指定的库。为了解决此问题,我们将深入研究如何指定库路径并将链接引导到正确位置的详细信息。添加库搜索路径的一个可能的原因是,此错误是您的makefile中缺少库搜索路径。要解决它,您可以在链接器命令中添加...
    编程 发布于2025-07-18
  • 如何在JavaScript对象中动态设置键?
    如何在JavaScript对象中动态设置键?
    在尝试为JavaScript对象创建动态键时,如何使用此Syntax jsObj['key' i] = 'example' 1;不工作。正确的方法采用方括号: jsobj ['key''i] ='example'1; 在JavaScript中,数组是一...
    编程 发布于2025-07-18
  • 为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    在CSS 问题:不正确的代码: 全球范围将所有余量重置为零,如提供的代码所建议的,可能会导致意外的副作用。解决特定的保证金问题是更建议的。 例如,在提供的示例中,将以下代码添加到CSS中,将解决余量问题: body H1 { 保证金顶:-40px; } 此方法更精确,避免了由全局保证金重置引...
    编程 发布于2025-07-18
  • 如何使用Regex在PHP中有效地提取括号内的文本
    如何使用Regex在PHP中有效地提取括号内的文本
    php:在括号内提取文本在处理括号内的文本时,找到最有效的解决方案是必不可少的。一种方法是利用PHP的字符串操作函数,如下所示: 作为替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式来搜索特...
    编程 发布于2025-07-18

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3