React.memo 和 useMemo 的使用問題小結(jié)
問題背景
大家在使用 React 框架進(jìn)行開發(fā)時(shí)一定遇到過以下問題:
- 當(dāng)函數(shù)式組件中的某一狀態(tài)改變,整個(gè)組件刷新,重新渲染
- 在類組件中 setState() 時(shí),整個(gè)組件也會(huì)重新渲染
- 以上問題若不進(jìn)行優(yōu)化,導(dǎo)致的結(jié)果是:
- 隨著代碼的增加,每次的狀態(tài)改變,頁(yè)面進(jìn)行一次 reRender ,這將產(chǎn)生很多不必要的 reRender 不僅浪費(fèi)性能,從而導(dǎo)致頁(yè)面卡頓;
useMemo 進(jìn)行優(yōu)化
以下面 App 組件進(jìn)行分析
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('運(yùn)行了useMemo num值為:', num); return num + 1 }, [num]) console.log('memoVal值為:', memoVal) console.log('父組件運(yùn)行分割線----------------------------------------------------') 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秒后的執(zhí)行結(jié)構(gòu)如下圖所示:
很顯然首次渲染執(zhí)行了,useMemo,而2秒后有狀態(tài)變化后沒有執(zhí)行useMemo。
點(diǎn)擊按鈕改變 useMemo 的依賴項(xiàng)后可以發(fā)現(xiàn),如下圖所示 useMemo 又執(zhí)行了。
因此在使用函數(shù)式組件時(shí),可以使用 useMemo 減少不必要的reRender 提高組件的性能;
React.memo 進(jìn)行優(yōu)化
在以上組件的基礎(chǔ)上,給App 增加一個(gè)子組件,代碼如下所示:
import React from 'react' export default function Children(props) { console.log('子組件運(yùn)行了,接收的props是', props) console.log('子組件渲染分割線------------------------------------------') return <div>子組件</div> }
首次render 以及 2s后組件的 reRender 控制臺(tái)打印結(jié)果如下圖所示:
由上圖可以看出,reRender 時(shí)Children 組件的props并未變化,因此,此次Children 組件的reRender 是不必要的,需要進(jìn)行優(yōu)化;
props的值是基本類型
如果 Children 的 props 是基本類型,則可以做一下優(yōu)化:
import React, { memo } from 'react' function Children(props) { console.log('子組件運(yùn)行了,接收的props是', props) console.log('子組件渲染分割線------------------------------------------') return <div>子組件</div> } export default memo(Children)
優(yōu)化后控制臺(tái)打印如下信息,一下信息可以看出 Children 組件沒有進(jìn)行 reRender
props的值是引用類型
若子組件的 props 是引用類型 ,則需要進(jìn)行深度比較,此時(shí)React.memo()要傳入第二個(gè)參數(shù)進(jìn)行深度比較,改變后 Children 組件的代碼如下所示:
import React, { memo } from 'react' function Children(props) { console.log('子組件運(yùn)行了,接收的props是', props) console.log('子組件渲染分割線------------------------------------------') return <div>子組件</div> } export default memo(Children, (preProps, nextProps) => { return JSON.stringify(preProps) === JSON.stringify(nextProps) })
以上 memo 第二個(gè)參數(shù) ,通過比較 preProps 和 nextProps 返回一個(gè)布爾值,使得props 進(jìn)行深度比較;注意:React.memo的第二個(gè)參數(shù)進(jìn)行深度比較時(shí)有一定開銷,其產(chǎn)生的開銷存在大于子組件reRender的可能
寫在最后
useMemo() 和 React.memo() 都是進(jìn)行組件性能優(yōu)化的方式,其區(qū)別是
- useMemo 可以進(jìn)行更加細(xì)粒度的優(yōu)化(有依賴項(xiàng))
- React.memo() 可以控制props的淺比較和深度比較
- React.memo在沒有第二個(gè)參數(shù)的時(shí)候相當(dāng)于class中的PureComponent,當(dāng)增加了第二個(gè)參數(shù)的時(shí)候相當(dāng)于生命周期中的shouldComponentUpdate;
到此這篇關(guān)于React.memo 和 useMemo 的使用問題小結(jié)的文章就介紹到這了,更多相關(guān)React.memo 和 useMemo內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React的組件協(xié)同使用實(shí)現(xiàn)方式
這篇文章主要介紹了React的組件協(xié)同使用,文中給大家提到在React開發(fā)中,有哪些場(chǎng)景的組件協(xié)同?又如何去實(shí)現(xiàn)組件的協(xié)同使用呢?本文都給大家提到,感興趣的朋友跟隨小編一起看看吧2021-09-09React實(shí)現(xiàn)一個(gè)拖拽排序組件的示例代碼
這篇文章主要給大家介紹了React實(shí)現(xiàn)一個(gè)拖拽排序組件?-?支持多行多列、支持TypeScript、支持Flip動(dòng)畫、可自定義拖拽區(qū)域,文章通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11react搭建環(huán)境時(shí)執(zhí)行npm start報(bào)錯(cuò)start: 'react-scripts&
這篇文章主要介紹了react搭建環(huán)境時(shí)執(zhí)行npm start報(bào)錯(cuò)start: 'react-scripts start'的解決方案,具有很好的參考價(jià)值,希望杜對(duì)大家有所幫助,2023-10-10使用React?MUI庫(kù)實(shí)現(xiàn)用戶列表分頁(yè)功能
MUI是一款基于React的UI組件庫(kù),可以方便地構(gòu)建美觀的用戶界面,使用MUI的DataTable組件和分頁(yè)器組件可以輕松實(shí)現(xiàn)用戶列表分頁(yè)功能,這篇文章使用MUI庫(kù)實(shí)現(xiàn)了用戶列表分頁(yè)功能,感興趣的同學(xué)可以參考下文2023-05-05在React項(xiàng)目中使用Eslint代碼檢查工具及常見問題
這篇文章主要介紹了在React項(xiàng)目中使用Eslint代碼檢查工具及常見問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10react?路由權(quán)限動(dòng)態(tài)菜單方案配置react-router-auth-plus
這篇文章主要為大家介紹了react路由權(quán)限動(dòng)態(tài)菜單方案react-router-auth-plus傻瓜式配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08減少react組件不必要的重新渲染實(shí)現(xiàn)方法
這篇文章主要為大家介紹了減少react組件不必要的重新渲染實(shí)現(xiàn)方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01