返回一個(gè) memoized 值
// useMemo返回一個(gè)值(可以是函數(shù))
const computeExpensiveValue = (a, b) => {
return a + b;
}
const memoizedValue = useMemo(computeExpensiveValue(a, b), [a, b]);
// useCallbak返回一個(gè)函數(shù)
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
- useMemo和useCallback解決的因函數(shù)更新而渲染自己的問(wèn)題
- 它僅會(huì)在某個(gè)依賴項(xiàng)改變時(shí)才重新計(jì)算 memoized 值
- 傳入
useMemo
的函數(shù)會(huì)在渲染期間執(zhí)行 - 副作用屬于
useEffect
的適用范疇,而不是useMemo
- 如果沒(méi)有提供依賴項(xiàng)數(shù)組嘿架,
useMemo
在每次渲染時(shí)都會(huì)計(jì)算新的值 -
useCallback(fn, deps)
相當(dāng)于useMemo(() => fn, deps)
瓶珊。
與React.memo的區(qū)別
- react.memo解決的是因父組件state變化因?yàn)榈淖越M件重復(fù)刷新的問(wèn)題
- React.memo的用法
function MyComponent(props) {
}
function areEqual(prevProps, nextProps) {
// 手動(dòng)判斷是否需要重新渲染
// return true不渲染,false則渲染
}
export default React.memo(MyComponent, areEqual);
問(wèn)題
-
React.memo
第二個(gè)參數(shù)不用的話默認(rèn)就 props 淺比較 -
React.memo
在跟某些hooks配合使用的情況下會(huì)失效耸彪,例如在組件內(nèi)部使用useState
伞芹,useReducer
,useContext
蝉娜,當(dāng) state 或者 context 改變時(shí)唱较,組件還是會(huì)重新渲染
import React, { useState } from "react";
function Child1(props) {
console.log("執(zhí)行子組件1了");
return <div>子組件1上的n:{props.value}</div>;
}
function Child2(props) {
console.log("執(zhí)行子組件2了");
return <div>子組件2上的m:{props.value}</div>;
}
const MChild1 = React.memo(Child1, () => {
return false; // 失效
}); // compare失效會(huì)直接導(dǎo)致整個(gè)React.memo失效
const MChild2 = React.memo(Child2);
export default function App() {
const [n, setN] = useState(0);
const [m, setM] = useState(10);
console.log("執(zhí)行最外層盒子了");
// 這里與是否是箭頭函數(shù)無(wú)關(guān)
function addM() {
setM(m + 1);
}
// 只要是復(fù)雜類型,都會(huì)渲染
const test = { a: 134 }; // 如果test是簡(jiǎn)單類型召川,則不會(huì)重復(fù)渲染
return (
<>
<div>
最外層盒子
<MChild1 value={n} test={test}/>
<MChild2 value={m} addM={addM} />
<button
onClick={() => {
setN(n + 1);
}}
>
n+1
</button>
<button
onClick={addM}
>
m+1
</button>
</div>
</>
);
}
問(wèn)題
- 自定義的compare函數(shù)失效南缓,導(dǎo)致整個(gè)React.memo失效
- App重新執(zhí)行了,它會(huì)修改復(fù)雜數(shù)據(jù)類型的地址荧呐,從而引發(fā)重新渲染
- useMemo解決addN和addM地址變更引發(fā)的重復(fù)渲染的問(wèn)題
import React, { useState, useMemo, useCallback, memo } from "react";
const Child1 = memo((props) => {
console.log("執(zhí)行子組件1了");
return <div>子組件1上的n:{props.value}</div>;
})
const Child2 = memo((props) => {
console.log("執(zhí)行子組件2了");
return <div>子組件2上的m:{props.value.m}</div>;
})
export default function App() {
const [n, setN] = useState(0);
const [m, setM] = useState({ m: 1 });
console.log("執(zhí)行最外層盒子了");
const addN = useMemo(() => {
return () => {
setN(n + 1);
};
}, [n]);
const addM = useCallback(() => {
setM({ m: m.m + 1 });
}, [m]);
return (
<>
<div>
最外層盒子
<Child1 value={n} click={addN} />
<Child2 value={m} click={addM} />
<button onClick={addN}>n+1</button>
<button onClick={addM}>m+1</button>
</div>
</>
);
}