日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

React.memo?和?useMemo?的使用問題小結_React

作者:前端小二哥 ? 更新時間: 2022-12-06 編程語言

問題背景

大家在使用 React 框架進行開發時一定遇到過以下問題:

  • 當函數式組件中的某一狀態改變,整個組件刷新,重新渲染
  • 在類組件中 setState() 時,整個組件也會重新渲染
  • 以上問題若不進行優化,導致的結果是:
  • 隨著代碼的增加,每次的狀態改變,頁面進行一次 reRender ,這將產生很多不必要的 reRender 不僅浪費性能,從而導致頁面卡頓;

useMemo 進行優化

以下面 App 組件進行分析

import './App.css';
import ProfileTest from './components';
import { Profiler, useEffect, useMemo, useState, useRef } from 'react'
function App () {
  const [name, setName] = useState('')
  const [num, setNum] = useState(0)
  useEffect(() => {
    setTimeout(() => {
      console.log('111')
      setName('xxx')
    }, 2000)
  }, [])
  const memoVal = useMemo(() => {
    console.log('運行了useMemo num值為:', num);
    return num + 1
  }, [num])
  console.log('memoVal值為:', memoVal)
  console.log('父組件運行分割線----------------------------------------------------')
  const changeNum = () => {
    setNum(2)
  }
  return (
    <Profiler id='profile-test'>
      <div className="App">
        {/* <ProfileTest /> */}
        <button style={{ marginTop: 100 }} onClick={changeNum}>改變num</button>
      </div>
    </Profiler>
  );
}
export default App;

以上組件在首次渲染、以及 2秒后的執行結構如下圖所示:

很顯然首次渲染執行了,useMemo,而2秒后有狀態變化后沒有執行useMemo。
點擊按鈕改變 useMemo 的依賴項后可以發現,如下圖所示 useMemo 又執行了。

因此在使用函數式組件時,可以使用 useMemo 減少不必要的reRender 提高組件的性能;

React.memo 進行優化

在以上組件的基礎上,給App 增加一個子組件,代碼如下所示:

import React from 'react'

export default function Children(props) {
  console.log('子組件運行了,接收的props是', props)
  console.log('子組件渲染分割線------------------------------------------')
  return <div>子組件</div>
}

首次render 以及 2s后組件的 reRender 控制臺打印結果如下圖所示:

由上圖可以看出,reRender 時Children 組件的props并未變化,因此,此次Children 組件的reRender 是不必要的,需要進行優化;

props的值是基本類型

如果 Children 的 props 是基本類型,則可以做一下優化:

import React, { memo } from 'react'

function Children(props) {
  console.log('子組件運行了,接收的props是', props)
  console.log('子組件渲染分割線------------------------------------------')
  return <div>子組件</div>
}
export default memo(Children)

優化后控制臺打印如下信息,一下信息可以看出 Children 組件沒有進行 reRender

props的值是引用類型

若子組件的 props 是引用類型 ,則需要進行深度比較,此時React.memo()要傳入第二個參數進行深度比較,改變后 Children 組件的代碼如下所示:

import React, { memo } from 'react'

function Children(props) {
  console.log('子組件運行了,接收的props是', props)
  console.log('子組件渲染分割線------------------------------------------')
  return <div>子組件</div>
}
export default memo(Children, (preProps, nextProps) => {
  return JSON.stringify(preProps) === JSON.stringify(nextProps)
})

以上 memo 第二個參數 ,通過比較 preProps 和 nextProps 返回一個布爾值,使得props 進行深度比較;
注意:React.memo的第二個參數進行深度比較時有一定開銷,其產生的開銷存在大于子組件reRender的可能

寫在最后

useMemo() 和 React.memo() 都是進行組件性能優化的方式,其區別是

  • useMemo 可以進行更加細粒度的優化(有依賴項)
  • React.memo() 可以控制props的淺比較和深度比較
  • React.memo在沒有第二個參數的時候相當于class中的PureComponent,當增加了第二個參數的時候相當于生命周期中的shouldComponentUpdate;

原文鏈接:https://blog.csdn.net/qq_44588612/article/details/127613936

欄目分類
最近更新