」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 掌握 React 重新渲染:如何避免常見陷阱

掌握 React 重新渲染:如何避免常見陷阱

發佈於2024-11-03
瀏覽:629

Mastering React Re-renders: How to Avoid Common Pitfalls

1.介绍

想象一下:您刚刚构建了一个时尚、功能丰富的 React 应用程序,但突然间,性能开始下降。按钮感觉迟钝,数据更新时间太长,而且你不知道为什么。如果这听起来很熟悉,那么您并不孤单。如果处理不当,React 重新渲染通常是性能问题背后的无声罪魁祸首。

掌握 React 中的重新渲染对于旨在构建高效、可扩展应用程序的 Web 开发人员至关重要。让我们深入研究 React 重新渲染的工作原理,并发现优化性能、避免常见陷阱并将您的 React 应用程序转变为极快体验的实用策略。

2. React 重新渲染如何工作?

React 的重新渲染机制是其最强大的功能之一。它允许您的应用程序根据状态或属性的变化动态更新 UI。但是,如果不进行优化,此过程可能会导致不必要的重新渲染,从而导致性能下降。

简单来说,React 每次都会重新渲染:

  1. 组件的状态发生变化。
  2. 组件接收新的 props。
  3. 父组件重新渲染。

但是当组件重新渲染过于频繁时会发生什么?浏览器必须重新绘制屏幕,​​从而导致动画卡顿、交互缓慢和用户沮丧。现在,问问自己:有多少次您的应用程序感觉速度很慢,而您却无法确切地指出原因?

3.为什么过度重新渲染会损害性能

过多的重新渲染会产生多米诺骨牌效应,使您的整个应用程序变得缓慢。每次重新渲染发生时:

  1. React 使更改与虚拟 DOM 协调。
  2. 它计算对实际 DOM 进行的最少更新。
  3. 浏览器重新绘制屏幕。

在小型应用程序中,这可能不明显。但在具有深度嵌套组件和复杂状态管理的大型应用程序中,即使是最小的不必要的重新渲染也可能会形成性能瓶颈。

这是一个简单的例子:

const UserList = ({ users }) => {
  return users.map(user => 
{user.name}
); }; // Inside a parent component:

现在想象一下,每次父组件更新时,这个 UserList 都会重新呈现,即使用户没有更改。这就是问题所在。我们如何防止这种不必要的重新渲染?

4.常见陷阱(以及如何避免它们)

陷阱 1:不记忆函数和对象

每次父组件重新渲染时,它都会创建新的函数和对象引用,即使实际值没有改变。这会导致子组件不必要地重新渲染。

操作:使用 useCallback 和 useMemo 挂钩来记忆函数和对象。

const ParentComponent = () => {
  const handleClick = useCallback(() => {
    // some function logic
  }, []);

  const userDetails = useMemo(() => ({ name: "Rajesh", age: 30 }), []);

  return ;
};

为什么有效: 记忆化可以防止在每次重新渲染时创建新的函数和对象引用,从而减少子组件中不必要的渲染。

陷阱 2:将内联函数或对象作为 Props 传递

每次组件渲染时都会创建内联函数或对象,导致接收组件重新渲染,即使实际值没有更改。

操作:在组件外部声明函数和对象或使用记忆挂钩。

// Avoid this:
 console.log("clicked")} />

// Instead:
const handleClick = useCallback(() => console.log("clicked"), []);

陷阱3:未能使用React.memo

一些组件本质上是纯粹的——它们总是在给定相同的 props 的情况下渲染相同的输出。然而,如果没有 React.memo,当父组件重新渲染时,它们仍然会重新渲染。

操作:用 React.memo 包裹功能组件,以防止不必要的重新渲染。

const ChildComponent = React.memo(({ data }) => {
  return 
{data.name}
; });

为什么有效: React.memo 确保组件仅在其 props 更改时重新渲染,避免冗余渲染。

5.如何跟踪和调试 React 重新渲染

有没有想过,“为什么我的组件会重新渲染?” React DevTools 提供了一种很好的方法来跟踪渲染并了解哪里出了问题。

  1. 启用“突出显示更新”:这会显示哪些组件正在重新渲染。
  2. 使用“Profiler”选项卡:它显示渲染计时并帮助识别瓶颈。

您还可以使用像这样的自定义挂钩来记录重新渲染:

const useWhyDidYouRender = (componentName, props) => {
  const previousProps = useRef(props);

  useEffect(() => {
    if (previousProps.current !== props) {
      console.log(`${componentName} re-rendered`);
      previousProps.current = props;
    }
  });
};

6。优化 React 重新渲染的最佳实践

1.在需要时提升状态,但并非总是如此

有时,将状态提升到更高的组件会导致子组件不必要的重新渲染。相反,尽可能在本地管理状态。

2.明智地使用密钥

渲染列表时,确保每个项目都有一个稳定、唯一的 key prop。这有助于 React 通过识别哪些项目已更改来优化重新渲染。

3.避免重新渲染未安装的组件

这可能会导致内存泄漏和性能问题。使用 useEffect 清理函数来避免在未挂载的组件中重新渲染。

useEffect(() => {
  return () => {
    // cleanup logic here
  };
}, []);

7.总结:掌握 React 重新渲染

简而言之,React 重新渲染可能是性能问题的隐藏根源,但通过正确的技术,您可以防止不必要的重新渲染,保持应用程序快速运行,并确保流畅的用户体验。

  • 记忆函数和对象以避免重新渲染子组件。
  • 使用 React.memo 停止纯组件中不必要的重新渲染。
  • 利用 React DevTools 跟踪、了解和调试性能瓶颈。

8.实际应用:通过有意的重新渲染提高性能

下次你优化 React 应用程序时,请批判性地思考每次重新渲染。它们有必要吗?如果你记住这个函数会发生什么?通过应用这些策略,您将编写更精简、更快的 React 代码,并避免即使是最有经验的开发人员也会遇到的常见陷阱。


最终想法: 既然您已经了解了 React 重新渲染的细节,请继续将这些优化应用到您自己的应用程序中。您不仅会看到更好的性能,还会获得编写可扩展、可维护的 React 代码的信心!


版本聲明 本文轉載於:https://dev.to/paharihacker/mastering-react-re-renders-how-to-avoid-common-pitfalls-k01?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 為什麼我會收到MySQL錯誤#1089:錯誤的前綴密鑰?
    為什麼我會收到MySQL錯誤#1089:錯誤的前綴密鑰?
    mySQL錯誤#1089:錯誤的前綴鍵錯誤descript [#1089-不正確的前綴鍵在嘗試在表中創建一個prefix鍵時會出現。前綴鍵旨在索引字符串列的特定前綴長度長度,以便更快地搜索這些前綴。 理解prefix keys `這將在整個Movie_ID列上創建標準主鍵。主密鑰對於唯一識...
    程式設計 發佈於2025-07-18
  • 如何將MySQL數據庫添加到Visual Studio 2012中的數據源對話框中?
    如何將MySQL數據庫添加到Visual Studio 2012中的數據源對話框中?
    在Visual Studio 2012 儘管已安裝了MySQL Connector v.6.5.4,但無法將MySQL數據庫添加到實體框架的“ DataSource對話框”中。為了解決這一問題,至關重要的是要了解MySQL連接器v.6.5.5及以後的6.6.x版本將提供MySQL的官方Visual...
    程式設計 發佈於2025-07-18
  • Go語言垃圾回收如何處理切片內存?
    Go語言垃圾回收如何處理切片內存?
    Garbage Collection in Go Slices: A Detailed AnalysisIn Go, a slice is a dynamic array that references an underlying array.使用切片時,了解垃圾收集行為至關重要,以避免潛在的內存洩...
    程式設計 發佈於2025-07-18
  • 如何使用node-mysql在單個查詢中執行多個SQL語句?
    如何使用node-mysql在單個查詢中執行多個SQL語句?
    Multi-Statement Query Support in Node-MySQLIn Node.js, the question arises when executing multiple SQL statements in a single query using the node-mys...
    程式設計 發佈於2025-07-18
  • 解決MySQL插入Emoji時出現的\\"字符串值錯誤\\"異常
    解決MySQL插入Emoji時出現的\\"字符串值錯誤\\"異常
    Resolving Incorrect String Value Exception When Inserting EmojiWhen attempting to insert a string containing emoji characters into a MySQL database us...
    程式設計 發佈於2025-07-18
  • 將圖片浮動到底部右側並環繞文字的技巧
    將圖片浮動到底部右側並環繞文字的技巧
    在Web設計中圍繞在Web設計中,有時可以將圖像浮動到頁面右下角,從而使文本圍繞它纏繞。這可以在有效地展示圖像的同時創建一個吸引人的視覺效果。 css位置在右下角,使用css float and clear properties: img { 浮點:對; ...
    程式設計 發佈於2025-07-18
  • 如何為PostgreSQL中的每個唯一標識符有效地檢索最後一行?
    如何為PostgreSQL中的每個唯一標識符有效地檢索最後一行?
    postgresql:為每個唯一標識符在postgresql中提取最後一行,您可能需要遇到與數據集合中每個不同標識的信息相關的信息。考慮以下數據:[ 1 2014-02-01 kjkj 在數據集中的每個唯一ID中檢索最後一行的信息,您可以在操作員上使用Postgres的有效效率: id dat...
    程式設計 發佈於2025-07-18
  • 為什麼不使用CSS`content'屬性顯示圖像?
    為什麼不使用CSS`content'屬性顯示圖像?
    在Firefox extemers屬性為某些圖像很大,&& && && &&華倍華倍[華氏華倍華氏度]很少見,卻是某些瀏覽屬性很少,尤其是特定於Firefox的某些瀏覽器未能在使用內容屬性引用時未能顯示圖像的情況。這可以在提供的CSS類中看到:。 googlepic { 內容:url(&...
    程式設計 發佈於2025-07-18
  • Python高效去除文本中HTML標籤方法
    Python高效去除文本中HTML標籤方法
    在Python中剝離HTML標籤,以獲取原始的文本表示Achieving Text-Only Extraction with Python's MLStripperTo streamline the stripping process, the Python standard librar...
    程式設計 發佈於2025-07-18
  • 如何在JavaScript對像中動態設置鍵?
    如何在JavaScript對像中動態設置鍵?
    在嘗試為JavaScript對象創建動態鍵時,如何使用此Syntax jsObj['key' i] = 'example' 1;不工作。正確的方法採用方括號: jsobj ['key''i] ='example'1; 在JavaScript中,數組是一...
    程式設計 發佈於2025-07-18
  • 在Java中使用for-to-loop和迭代器進行收集遍歷之間是否存在性能差異?
    在Java中使用for-to-loop和迭代器進行收集遍歷之間是否存在性能差異?
    For Each Loop vs. Iterator: Efficiency in Collection TraversalIntroductionWhen traversing a collection in Java, the choice arises between using a for-...
    程式設計 發佈於2025-07-18
  • 反射動態實現Go接口用於RPC方法探索
    反射動態實現Go接口用於RPC方法探索
    在GO 使用反射來實現定義RPC式方法的界面。例如,考慮一個接口,例如:鍵入myService接口{ 登錄(用戶名,密碼字符串)(sessionId int,錯誤錯誤) helloworld(sessionid int)(hi String,錯誤錯誤) } 替代方案而不是依靠反射...
    程式設計 發佈於2025-07-18
  • 在PHP中如何高效檢測空數組?
    在PHP中如何高效檢測空數組?
    在PHP 中檢查一個空數組可以通過各種方法在PHP中確定一個空數組。如果需要驗證任何數組元素的存在,則PHP的鬆散鍵入允許對數組本身進行直接評估:一種更嚴格的方法涉及使用count()函數: if(count(count($ playerList)=== 0){ //列表為空。 } 對...
    程式設計 發佈於2025-07-18
  • C++中如何將獨占指針作為函數或構造函數參數傳遞?
    C++中如何將獨占指針作為函數或構造函數參數傳遞?
    在構造函數和函數中將唯一的指數管理為參數 unique pointers( unique_ptr [2啟示。通過值: base(std :: simelor_ptr n) :next(std :: move(n)){} 此方法將唯一指針的所有權轉移到函數/對象。指針的內容被移至功能中,在操作...
    程式設計 發佈於2025-07-18
  • Java中假喚醒真的會發生嗎?
    Java中假喚醒真的會發生嗎?
    在Java中的浪費喚醒:真實性或神話? 在Java同步中偽裝喚醒的概念已經是討論的主題。儘管存在這種行為的潛力,但問題仍然存在:它們實際上是在實踐中發生的嗎? Linux的喚醒機制根據Wikipedia關於偽造喚醒的文章,linux實現了pthread_cond_wait()功能的Linux實現,...
    程式設計 發佈於2025-07-18

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

Copyright© 2022 湘ICP备2022001581号-3