react提供useMemo/useCallback/memo方法,提高頁(yè)面刷新效率。若組件依賴的屬性沒(méi)有發(fā)送變化,組件可以不刷新。以下提供兩個(gè)場(chǎng)景的具體使用
單組件內(nèi)使用
使用語(yǔ)法
import React, { useMemo } from 'react'
useMemo(() => {}, [] )
- 1.
useMemo第一個(gè)參數(shù)是函數(shù),第二個(gè)參數(shù)是數(shù)組 - 2.如果第二個(gè)參數(shù)不傳遞,與
useEffect類似,意味著每次都會(huì)執(zhí)行第一個(gè)函數(shù)參數(shù),則使用useMem就毫無(wú)意義 - 3.如果第二個(gè)參數(shù)傳的是空數(shù)組
[], 與useEffect類似,只執(zhí)行一次,類似類組件componentDidmount - 4.
useMemo與useEffect有不一樣的一點(diǎn)就是調(diào)用時(shí)機(jī) —— useEffect執(zhí)行的是副作用,所以一定是在渲染之后運(yùn)行的;而useMemo是需要有返回值的,返回值會(huì)參與渲染,所以u(píng)seMemo是是在渲染期間完成的。 - 5.
useMemo,定義了一段函數(shù)邏輯,根據(jù)第二個(gè)參數(shù)判斷是否執(zhí)行第一個(gè)函數(shù)執(zhí)行
useMemo
case1 (不設(shè)置第二個(gè)參數(shù),無(wú)優(yōu)化效果)
-
useMemo第二個(gè)參數(shù)不設(shè)置 - 代碼表現(xiàn):每次點(diǎn)擊
點(diǎn)擊+1,控制臺(tái)打印double,同時(shí)標(biāo)簽Double每次刷新 - 代碼解析:
useMemo第二個(gè)參數(shù)不設(shè)置,頁(yè)面首次加載和頁(yè)面更新,都會(huì)重新加載<div>Double is :{double}</div>
import React, {useState, useCallback, useEffect, useMemo, memo} from 'react'
// 函數(shù)組件,當(dāng)前組件中useMemo的使用
function App() {
const [count, setCount] = useState(0)
const double = useMemo(()=>{
console.log('double')
return count * 2
})//關(guān)注點(diǎn)
return (
<div>
<button onClick={() => {
setCount(count + 1)
}}>點(diǎn)擊+1
</button>
<div>Count is :{count}</div>
<div>Double is :{double}</div>
</div>
)
}
case2 (設(shè)置第二個(gè)參數(shù)為[],首次加載更新)
-
useMemo第二個(gè)參數(shù)設(shè)置為[],這組件只會(huì)在頁(yè)面首次加載更新,類似類組件的componentDidMount - 代碼表現(xiàn):頁(yè)面首次加載,控制臺(tái)打印
double;每次點(diǎn)擊點(diǎn)擊+1,控制臺(tái)打印無(wú)打印日志,同時(shí)標(biāo)簽Double始終為0 - 代碼解析:
useMemo第二個(gè)參數(shù)設(shè)置[],<div>Double is :{double}</div>只有在首次頁(yè)面加載,即double變化了,也不會(huì)改變標(biāo)簽的
import React, {useState, useCallback, useEffect, useMemo, memo} from 'react'
// 函數(shù)組件,當(dāng)前組件中useMemo的使用
function App() {
const [count, setCount] = useState(0)
const double = useMemo(()=>{
console.log('double')
return count * 2
},[]) //關(guān)注點(diǎn)
return (
<div>
<button onClick={() => {
setCount(count + 1)
}}>點(diǎn)擊+1
</button>
<div>Count is :{count}</div>
<div>Double is :{double}</div>
</div>
)
}
case3 (設(shè)置第二個(gè)參數(shù)為[count===2])
-
useMemo第二個(gè)參數(shù)設(shè)置為[count===2] - 代碼表現(xiàn):頁(yè)面首次加載,控制臺(tái)打印
double;點(diǎn)擊點(diǎn)擊+1,當(dāng)count=2,count=3的時(shí)候控制臺(tái)打印double,同時(shí)標(biāo)簽<div>Double is :{double}</div>更新兩次,分別為Double is :4和Double is :6 - 代碼解析:
useMemo第二個(gè)參數(shù)設(shè)置[count===2],表示當(dāng)count===2的時(shí)候才會(huì)更新組件,count從1,2,3對(duì)應(yīng)count===2變化為false, true, false,因此只有2次刷新
import React, {useState, useCallback, useEffect, useMemo, memo} from 'react'
// 函數(shù)組件,當(dāng)前組件中useMemo的使用
function App() {
const [count, setCount] = useState(0)
const double = useMemo(()=>{
console.log('double')
return count * 2
},[count===2]) //關(guān)注點(diǎn)
return (
<div>
<button onClick={() => {
setCount(count + 1)
}}>點(diǎn)擊+1
</button>
<div>Count is :{count}</div>
<div>Double is :{double}</div>
</div>
)
}
父子組件內(nèi)使用
目標(biāo):
子組件的依賴屬性更新,才會(huì)重新加載子組件
操作:
- 1.子組件用
memo聲明, - 2.子組件對(duì)父組件依賴的
所有屬性用useCallback或者useMemo聲明
子組件沒(méi)用memo聲明
程序響應(yīng):
-
<Counter counter = {double}></Counter>當(dāng)count為2,3的時(shí)候,double發(fā)生變化
-
- 2.每次
count變化,子組件都會(huì)重新渲染(控制臺(tái)打印日志counter)
代碼如下
function Counter(props) {
console.log('counter')
return (
<div>
double is : {props.counter}
</div>
)
}
function App (){
const [count, setCount] = useState(0)
const double = useMemo(()=>{
return count * 2
}, [count === 2])
return (
<div>
<button onClick={()=>{setCount(count + 1)}}>點(diǎn)擊+1</button>
<div>count is : {count}</div>
<Counter counter = {double}></Counter>
</div>
)
}
子組件用memo聲明
程序響應(yīng):
-
<Counter counter = {double}></Counter>當(dāng)count為2,3的時(shí)候,double發(fā)生變化
-
- 2.當(dāng)count為2,3的時(shí)候,子組件會(huì)重新渲染(控制臺(tái)打印日志
counter)
代碼如下
const Counter = memo(function Counter(props) {
console.log('counter')
return (
<div>
double is : {props.counter}
</div>
)
})
function App (){
const [count, setCount] = useState(0)
const double = useMemo(()=>{
return count * 2
}, [count === 2])
return (
<div>
<button onClick={()=>{setCount(count + 1)}}>點(diǎn)擊+1</button>
<div>count is : {count}</div>
<Counter counter = {double}></Counter>
</div>
)
}
子組件用部分屬性useMemo聲明
程序響應(yīng):
-
<Counter counter = {double}></Counter>當(dāng)count為2,3的時(shí)候,double發(fā)生變化
-
- 2.每次
count變化,子組件都會(huì)重新渲染(控制臺(tái)打印日志counter),原因是btnClick是箭頭函數(shù)定義的,react頁(yè)面更新都會(huì)重新渲染子組件
代碼
//函數(shù)組件,父組件,子組件
const Counter = memo(function Counter(props) {
console.log('counter')
return (
<div>
double is : {props.counter}
</div>
)
})
function App (){
const [count, setCount] = useState(0)
const double = useMemo(()=>{
return count * 2
}, [count === 2])
const btnClick = ()=>{
console.log('click')
}
return (
<div>
<button onClick={()=>{setCount(count + 1)}}>點(diǎn)擊+1</button>
<div>count is : {count}</div>
<Counter counter = {double} onClick={btnClick}></Counter>
</div>
)
}
子組件用全部屬性useMemo/useCallback聲明
程序響應(yīng):
-
<Counter counter = {double}></Counter>當(dāng)count為2,3的時(shí)候,double發(fā)生變化
-
- 2.當(dāng)count為2,3的時(shí)候,子組件會(huì)重新渲染(控制臺(tái)打印日志
counter) -
const btnClick = useCallback(()=>{console.log('click')}, []), 關(guān)注useCallback第二個(gè)參數(shù),
** a.當(dāng)?shù)诙€(gè)參數(shù)不設(shè)置,則每次count變化,子組件都會(huì)重新加載,即使counter = {double}不發(fā)生變化,因?yàn)閎tnClick是首次加載和更新都會(huì)重新加載,導(dǎo)致子組件也會(huì)重新加載
** b.當(dāng)?shù)诙€(gè)參數(shù)為[]出現(xiàn)2的現(xiàn)象,原因是子組件的double發(fā)生變化
** c.當(dāng)?shù)诙€(gè)參數(shù)為[double]出現(xiàn)2的現(xiàn)象,原因是double發(fā)生比變化
-
代碼
//函數(shù)組件,父組件,子組件
const Counter = memo(function Counter(props) {
console.log('counter')
return (
<div>
double is : {props.counter}
</div>
)
})
function App (){
const [count, setCount] = useState(0)
const double = useMemo(()=>{
return count * 2
}, [count === 2])
const btnClick = useCallback(()=>{
console.log('click')
}, [])
return (
<div>
<button onClick={()=>{setCount(count + 1)}}>點(diǎn)擊+1</button>
<div>count is : {count}</div>
<Counter counter = {double} onClick={btnClick}></Counter>
</div>
)
}