」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 如何防止不必要的 React 元件重新渲染

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

發佈於2024-11-14
瀏覽:208

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]刪除
最新教學 更多>
  • Go web應用何時關閉數據庫連接?
    Go web應用何時關閉數據庫連接?
    在GO Web Applications中管理數據庫連接很少,考慮以下簡化的web應用程序代碼:出現的問題:何時應在DB連接上調用Close()方法? ,該特定方案將自動關閉程序時,該程序將在EXITS EXITS EXITS出現時自動關閉。但是,其他考慮因素可能保證手動處理。 選項1:隱式關閉終...
    程式設計 發佈於2025-05-01
  • C++20 Consteval函數中模板參數能否依賴於函數參數?
    C++20 Consteval函數中模板參數能否依賴於函數參數?
    [ consteval函數和模板參數依賴於函數參數在C 17中,模板參數不能依賴一個函數參數,因為編譯器仍然需要對非contexexpr futcoriations contim at contexpr function進行評估。 compile time。 C 20引入恆定函數,必須在編譯時進...
    程式設計 發佈於2025-05-01
  • 如何在Chrome中居中選擇框文本?
    如何在Chrome中居中選擇框文本?
    選擇框的文本對齊:局部chrome-inly-ly-ly-lyly solument 您可能希望將文本中心集中在選擇框中,以獲取優化的原因或提高可訪問性。但是,在CSS中的選擇元素中手動添加一個文本 - 對屬性可能無法正常工作。 初始嘗試 state)</option> < o...
    程式設計 發佈於2025-05-01
  • 在Java中如何為PNG文件添加坐標軸和標籤?
    在Java中如何為PNG文件添加坐標軸和標籤?
    如何用java 在現有png映像中添加軸和標籤的axes和labels如何註釋png文件可能具有挑戰性。與其嘗試可能導致錯誤和不一致的修改,不如建議在圖表創建過程中集成註釋。 使用JFReechArt import java.awt.color; 導入java.awt.eventqueue; 導...
    程式設計 發佈於2025-05-01
  • 找到最大計數時,如何解決mySQL中的“組函數\”錯誤的“無效使用”?
    找到最大計數時,如何解決mySQL中的“組函數\”錯誤的“無效使用”?
    如何在mySQL中使用mySql 檢索最大計數,您可能會遇到一個問題,您可能會在嘗試使用以下命令:理解錯誤正確找到由名稱列分組的值的最大計數,請使用以下修改後的查詢: 計數(*)為c 來自EMP1 按名稱組 c desc訂購 限制1 查詢說明 select語句提取名稱列和每個名稱...
    程式設計 發佈於2025-05-01
  • PHP與C++函數重載處理的區別
    PHP與C++函數重載處理的區別
    作為經驗豐富的C開發人員脫離謎題,您可能會遇到功能超載的概念。這個概念雖然在C中普遍,但在PHP中構成了獨特的挑戰。讓我們深入研究PHP功能過載的複雜性,並探索其提供的可能性。 在PHP中理解php的方法在PHP中,函數超載的概念(如C等語言)不存在。函數簽名僅由其名稱定義,而與他們的參數列表無關...
    程式設計 發佈於2025-05-01
  • 如何為PostgreSQL中的每個唯一標識符有效地檢索最後一行?
    如何為PostgreSQL中的每個唯一標識符有效地檢索最後一行?
    postgresql:為每個唯一標識符在postgresql中提取最後一行,您可能需要遇到與數據集合中每個不同標識的信息相關的信息。考慮以下數據:[ 1 2014-02-01 kjkj 在數據集中的每個唯一ID中檢索最後一行的信息,您可以在操作員上使用Postgres的有效效率: id dat...
    程式設計 發佈於2025-05-01
  • 如何從2D數組中提取元素?使用另一數組的索引
    如何從2D數組中提取元素?使用另一數組的索引
    Using NumPy Array as Indices for the 2nd Dimension of Another ArrayTo extract specific elements from a 2D array based on indices provided by a second ...
    程式設計 發佈於2025-05-01
  • 為什麼在我的Linux服務器上安裝Archive_Zip後,我找不到“ class \” class \'ziparchive \'錯誤?
    為什麼在我的Linux服務器上安裝Archive_Zip後,我找不到“ class \” class \'ziparchive \'錯誤?
    class'ziparchive'在Linux Server上安裝Archive_zip時找不到錯誤 commant in lin ins in cland ins in lin.11 on a lin.1 in a lin.11錯誤:致命錯誤:在... cass中找不到類z...
    程式設計 發佈於2025-05-01
  • JavaScript中如何動態訪問全局變量?
    JavaScript中如何動態訪問全局變量?
    在JavaScript 一種方法是使用窗口對象存儲和檢索變量。通過引用全局範圍,可以使用其名稱動態訪問變量。 //一個腳本 var somevarname_10 = 20; //另一個腳本 window.all_vars = {}; window.all_vars ['somevarna...
    程式設計 發佈於2025-05-01
  • 為什麼我在PHP中遇到“未定義函數mysql_connect()”錯誤?
    為什麼我在PHP中遇到“未定義函數mysql_connect()”錯誤?
    故障排除“未定義的函數mysql_connect()” 在嘗試使用mysql時,插入“未定義函數mysql_connect()”錯誤?這是解決此問題的綜合指南。 分析SolutionTo address this issue, you have two options:1.遷移到PDO或MySQL...
    程式設計 發佈於2025-05-01
  • 您可以使用CSS在Chrome和Firefox中染色控制台輸出嗎?
    您可以使用CSS在Chrome和Firefox中染色控制台輸出嗎?
    在javascript console 中顯示顏色是可以使用chrome的控制台顯示彩色文本,例如紅色的redors,for for for for錯誤消息? 回答是的,可以使用CSS將顏色添加到Chrome和Firefox中的控制台顯示的消息(版本31或更高版本)中。要實現這一目標,請使用以下...
    程式設計 發佈於2025-05-01
  • Java為何無法創建泛型數組?
    Java為何無法創建泛型數組?
    通用陣列創建錯誤 arrayList [2]; JAVA報告了“通用數組創建”錯誤。為什麼不允許這樣做? 答案:Create an Auxiliary Class:public static ArrayList<myObject>[] a = new ArrayList<my...
    程式設計 發佈於2025-05-01
  • 為什麼我的CSS背景圖像出現?
    為什麼我的CSS背景圖像出現?
    故障排除:CSS背景圖像未出現 ,您的背景圖像儘管遵循教程說明,但您的背景圖像仍未加載。圖像和样式表位於相同的目錄中,但背景仍然是空白的白色帆布。 而不是不棄用的,您已經使用了CSS樣式: bockent {背景:封閉圖像文件名:背景圖:url(nickcage.jpg); 如果您的html,cs...
    程式設計 發佈於2025-05-01
  • 如何有效地轉換PHP中的時區?
    如何有效地轉換PHP中的時區?
    在PHP 利用dateTime對象和functions DateTime對象及其相應的功能別名為時區轉換提供方便的方法。例如: //定義用戶的時區 date_default_timezone_set('歐洲/倫敦'); //創建DateTime對象 $ dateTime = ne...
    程式設計 發佈於2025-05-01

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3