iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0
Modern Web

30天React練功坊-攻克常見實務/面試問題系列 第 13

30天React練功坊-攻克常見實務/面試問題 Day13: ExpensiveComponent re-render causing performance issue

  • 分享至 

  • xImage
  •  
tags: ItIron2023 react

前言

我們昨天用了一個簡單的例子告訴你useRef在哪些情況能派上用場,那並不會是我們唯一一次與useRef打交道,若對那個hook還是有點模糊強烈推薦去補課!今天我們來看另一個常見的問題,這幾天我們都會將重點重新放回重新渲染這個部分,暫時忍耐一下,我保證你多少會有點收獲的。

本日題目

老樣子我們先看一下今天的codesandbox以及下方的gif檔案。

這同樣是個相當簡單的頁面,但其中包含著一個渲染成本相當昂貴的組件(ExpensiveComponent),這個組件接受來自父層的text state作為props,同時父組件也另外有個count state,但並沒有將count作為props傳給ExpensiveComponent。

觀察一下gif,你會發現當我們點擊更新text的按鈕時,ExpensiveComponent確實順利重新渲染,雖然你可以發現它比起App component,ExpensiveComponent需要花更多時間渲染。

day13-demo-gif

不過同時你也會發現,今天你即便只是更新count的值,ExpensiveComponent仍需要花費大量時間重新渲染,請試著解釋這個情況並修復此問題。

day13-demo-image

解答與基本解釋

今天題目我想並不複雜,若你之前的文章都有看過或是已經對react渲染的基本規則駕輕就熟了,關於為什麼ExpensiveComponent會因為count更新重新渲染想必是再簡單不過的問題了。最後一次強調,組件會重新渲染多半是

1. state或是props更新
2. 父組件重新渲染

今天這個不必要的重新渲染很明顯就是第二種情境,由於你更新count會讓App組件需要重新渲染,當App組件重新渲染時作為子組件的ExpensiveComponent自然也會被重新渲染,最終造成了你看到的情況。這類的情況其實遠比你想像的常見,實務上的ExpensiveComponent雖然不會有這麼白痴的寫法,但有些組件本身包含數十實甚至數百個小組件都不足為奇,若每次都隨意的重新渲染這樣的組件就會像今天的例子一樣,讓使用者感到明顯的卡頓。

解決方法相當的簡單,畢竟這是在react需要管的範疇中,他們有提供React.memo這樣的HOC(Higher Order Component)讓我們使用,React.memo會對此次傳入的props與上一次傳入的props做淺比對(shallow comparison),若判斷props有改變才會選擇觸發重新渲染,若沒有改變則skip渲染的過程,了解這點之後你只要將ExpensiveComponent稍稍做改動即可。

import React, { useState, memo } from "react";

const ExpensiveComponent = memo(({ data }) => { // 將ExpensiveComponent傳入memo中
  const startTime = performance.now();

  // Simulate expensive calculation
  for (let i = 0; i < 1000000000; i++) {}

  const endTime = performance.now();
  console.log(`ExpensiveComponent took ${endTime - startTime} ms to render.`);

  return <div>{data}</div>;
})

光是這樣改動你就會發現更新count值不再讓ExpensiveComponent重新渲染了,你可以盡情的去點increase count按鈕囉!

總結

我們今天再次看了一個不必要的重新渲染範例並將React.memo加入我們的系列文中,善用React.memo可以帶給你的使用者更好的體驗,但前提是你要善用它,若這是你第一次見到這玩意,老樣子,補課的部分交給你,永遠都先從官方文件開始!而若你已經接觸過React.memo,我相信你心裡會有些疑惑,覺得我是不是漏掉什麼了,那麼你是完全正確的,這部分我們等明天再繼續!

本文章同步發布於個人部落格,有興趣的朋友也可以來逛逛~!


上一篇
30天React練功坊-攻克常見實務/面試問題 Day12: Sometimes useState just not good enough
下一篇
30天React練功坊-攻克常見實務/面試問題 Day14: Optimization with React.memo the wrong way
系列文
30天React練功坊-攻克常見實務/面試問題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言